У меня возникла проблема с подключением GraphDiff объекта, который имеет рекурсивное отношение «многие ко многим». Я использую GraphDiff 2.0.1 и Entity Framework 6.1.1.GraphDiff и EF6.1 - Рекурсивное отношение «многие ко многим»
Прогма управляет рецептами, которые могут содержать 0-n RecipeLines, который содержит ссылку на другой рецепт, который является ComponentRecipe, и это имеет RecipeLines и т. Д.
Я передаю объект рецепта в репозиторий, который имеет 1 линию рецепта с объектом Рецепт на линии, указывающей на родительский объект и объект ComponentRecipe, указывающий на другой рецепт.
Когда GraphDiff присоединяет элемент, то прикрепленный элемент, который он возвращает, имеет 2 строки рецептов, и оба они одинаковы, и точка ComponentRecipe указывает на тот же объект, что и Recipe, который создает цикл сам по себе.
Я не уверен, что это проблема с GraphDiff или, скорее всего, у меня что-то не так в EF-сопоставлениях или в сопоставлениях GraphDiff. Любая помощь оценивается, дайте мне знать, если вам нужна дополнительная информация, и я могу предоставить простую программу, демонстрирующую эту проблему.
Доменные Модели
public class Recipe : EntityBase
{
public override object Key
{
get { return Id; }
}
public int Id { get; set; }
public string Name { get; set; }
public virtual IList<RecipeLine> RecipeLines { get; set; }
}
public class RecipeLine : EntityBase
{
public override object Key
{
get { return Id; }
}
public int Id { get; set; }
public int RecipeId { get; set; }
public int ComponentRecipeId { get; set; }
public decimal Quantity { get; set; }
public virtual Recipe Recipe { get; set; }
public virtual Recipe ComponentRecipe { get; set; }
}
Контекст данных
class DataContext : DbContext
{
public DataContext()
: base("Connection")
{
Configuration.ProxyCreationEnabled = false;
Configuration.LazyLoadingEnabled = false;
}
public DbSet<Recipe> Recipes { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<DataContext>(null);
modelBuilder.Entity<Recipe>().ToTable("Recipes");
modelBuilder.Entity<Recipe>().HasKey(x => x.Id);
modelBuilder.Entity<Recipe>().Property(x => x.Id).HasColumnName("Id");
modelBuilder.Entity<Recipe>().Property(x => x.Name).HasColumnName("Name");
modelBuilder.Entity<RecipeLine>().ToTable("RecipeLines");
modelBuilder.Entity<RecipeLine>().HasKey(x => x.Id);
modelBuilder.Entity<RecipeLine>().Property(x => x.Id).HasColumnName("Id");
modelBuilder.Entity<RecipeLine>().Property(x => x.RecipeId).HasColumnName("RecipeId");
modelBuilder.Entity<RecipeLine>().Property(x => x.ComponentRecipeId).HasColumnName("ComponentRecipeId");
modelBuilder.Entity<RecipeLine>().Property(x => x.Quantity).HasColumnName("Quantity").HasPrecision(18, 5);
modelBuilder.Entity<Recipe>().HasMany(x => x.RecipeLines).WithRequired(x => x.Recipe).HasForeignKey(x => x.RecipeId);
modelBuilder.Entity<RecipeLine>().HasRequired(x => x.ComponentRecipe).WithMany().HasForeignKey(x => x.ComponentRecipeId);
}
}
Repository
public override void UpdateEntity(IEntity entity)
{
using (var context = new DataContext())
{
context.Database.Log = s => System.Diagnostics.Debug.WriteLine(s);
var item = (Recipe)entity;
var attachedItem = context.UpdateGraph(item,
a => a.OwnedCollection(b => b.RecipeLines, c => c.AssociatedEntity(d => d.ComponentRecipe)));
context.SaveChanges();
}
}
Данные журнал контекста Приложить
Opened connection at 14/09/2014 16:57:06 +01:00
SELECT
[Project1].[Id] AS [Id],
[Project1].[Name] AS [Name],
[Project1].[C1] AS [C1],
[Project1].[Id1] AS [Id1],
[Project1].[RecipeId] AS [RecipeId],
[Project1].[ComponentRecipeId] AS [ComponentRecipeId],
[Project1].[Quantity] AS [Quantity],
[Project1].[Id2] AS [Id2],
[Project1].[Name1] AS [Name1]
FROM (SELECT
[Limit1].[Id] AS [Id],
[Limit1].[Name] AS [Name],
[Join1].[Id1] AS [Id1],
[Join1].[RecipeId] AS [RecipeId],
[Join1].[ComponentRecipeId] AS [ComponentRecipeId],
[Join1].[Quantity] AS [Quantity],
[Join1].[Id2] AS [Id2],
[Join1].[Name] AS [Name1],
CASE WHEN ([Join1].[Id1] IS NULL) THEN CAST(NULL AS int) ELSE 1 END AS [C1]
FROM (SELECT TOP (2) [Extent1].[Id] AS [Id], [Extent1].[Name] AS [Name]
FROM [dbo].[Recipes] AS [Extent1]
WHERE 11 = [Extent1].[Id]) AS [Limit1]
LEFT OUTER JOIN (SELECT [Extent2].[Id] AS [Id1], [Extent2].[RecipeId] AS [RecipeId], [Extent2].[ComponentRecipeId] AS [ComponentRecipeId], [Extent2].[Quantity] AS [Quantity], [Extent3].[Id] AS [Id2], [Extent3].[Name] AS [Name]
FROM [dbo].[RecipeLines] AS [Extent2]
INNER JOIN [dbo].[Recipes] AS [Extent3] ON [Extent2].[ComponentRecipeId] = [Extent3].[Id]) AS [Join1] ON [Limit1].[Id] = [Join1].[RecipeId]
) AS [Project1]
ORDER BY [Project1].[Id] ASC, [Project1].[C1] ASC
-- Executing at 14/09/2014 16:57:06 +01:00
-- Completed in 1 ms with result: SqlDataReader
Closed connection at 14/09/2014 16:57:06 +01:00
Opened connection at 14/09/2014 16:57:07 +01:00
SELECT
[Extent1].[Id] AS [Id],
[Extent1].[Name] AS [Name]
FROM [dbo].[Recipes] AS [Extent1]
WHERE [Extent1].[Id] = 10
-- Executing at 14/09/2014 16:57:07 +01:00
-- Completed in 0 ms with result: SqlDataReader
Closed connection at 14/09/2014 16:57:07 +01:00
контекста данных Вход на SaveChanges
Opened connection at 14/09/2014 16:58:45 +01:00
INSERT [dbo].[RecipeLines]([RecipeId], [ComponentRecipeId], [Quantity])
VALUES (@0, @1, @2)
SELECT [Id]
FROM [dbo].[RecipeLines]
WHERE @@ROWCOUNT > 0 AND [Id] = scope_identity()
-- @0: '11' (Type = Int32)
-- @1: '11' (Type = Int32)
-- @2: '1' (Type = Decimal, Precision = 18, Scale = 5)
-- Executing at 14/09/2014 16:58:46 +01:00
-- Completed in 1 ms with result: SqlDataReader
Closed connection at 14/09/2014 16:58:46 +01:00