Итак, вы просто делаете что-то не так. В дополнение к моему комментарию, я создал образец для вашего, который показывает, что по умолчанию EF не создает дубликаты.
У меня есть два класса:
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public ProductCategory Category { get; set; }
public decimal Price { get; set; }
}
public class ProductCategory
{
public int Id { get; set; }
public string Name { get; set; }
}
Один контекст:
public class MyContext : DbContext
{
public DbSet<Product> Products { get; set; }
public DbSet<ProductCategory> ProductCategories { get; set; }
public MyContext()
: base("name=MyContext")
{
}
public MyContext(string nameOrConnectionString)
: base(nameOrConnectionString)
{
}
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
Database.SetInitializer<MyContext>(null);
// Table mappings
modelBuilder.Entity<Product>().ToTable("Product");
modelBuilder.Entity<ProductCategory>().ToTable("ProductCategory");
base.OnModelCreating(modelBuilder);
}
}
Тогда один инициализатор класса (это может наследоваться от других стратегий, если вы хотите):
public class InitDb<TContext> : DropCreateDatabaseAlways<TContext>
where TContext : DbContext
{
}
The основная программа:
static void Main(string[] args)
{
var prodCat = new ProductCategory()
{
Name = "Category 1"
};
var prod = new Product()
{
Name = "Product 1",
Category = prodCat,
Price = 19.95M
};
using (var context = new MyContext())
{
var initializer = new InitDb<MyContext>();
initializer.InitializeDatabase(context);
Console.WriteLine("Adding products and categories to context.");
context.ProductCategories.Add(prodCat);
context.Products.Add(prod);
Console.WriteLine();
Console.WriteLine("Saving initial context.");
context.SaveChanges();
Console.WriteLine("Context saved.");
Console.WriteLine();
Console.WriteLine("Changing product details.");
var initProd = context.Products.Include(x => x.Category).SingleOrDefault(x => x.Id == 1);
PrintProduct(initProd);
initProd.Name = "Product 1 modified";
initProd.Price = 29.95M;
initProd.Category.Name = "Category 1 modified";
PrintProduct(initProd);
Console.WriteLine();
Console.WriteLine("Saving modified context.");
context.SaveChanges();
Console.WriteLine("Context saved.");
Console.WriteLine();
Console.WriteLine("Getting modified product from database.");
var modProd = context.Products.Include(x => x.Category).SingleOrDefault(x => x.Id == 1);
PrintProduct(modProd);
Console.WriteLine();
Console.WriteLine("Finished!");
Console.ReadKey();
}
}
static void PrintProduct(Product prod)
{
Console.WriteLine(new string('-', 10));
Console.WriteLine("Id : {0}", prod.Id);
Console.WriteLine("Name : {0}", prod.Name);
Console.WriteLine("Price : {0}", prod.Price);
Console.WriteLine("CatId : {0}", prod.Category.Id);
Console.WriteLine("CatName : {0}", prod.Category.Name);
Console.WriteLine(new string('-', 10));
}
Это приводит к следующему выходу консоли:
Adding products and categories to context.
Saving initial context.
Context saved.
Changing product details.
----------
Id : 1
Name : Product 1
Price : 19,95
CatId : 1
CatName : Category 1
----------
----------
Id : 1
Name : Product 1 modified
Price : 29,95
CatId : 1
CatName : Category 1 modified
----------
Saving modified context.
Context saved.
Getting modified product from database.
----------
Id : 1
Name : Product 1 modified
Price : 29,95
CatId : 1
CatName : Category 1 modified
----------
Finished!
Кроме того, при поиске в SQL Server Management Studio, это решение только создал (и обновляется) один продукт и одну категорию.
Конечно, вы должны работать с репозиториями для извлечения, обновления и удаления ваших данных и единицы работы. Они были исключены из примера.
Так что, если вы не размещать код, мы не можем помочь вам гораздо дальше :-)
Можете ли вы добавить код, в котором вы создаете данные? Если ваши ссылки в ваших классах верны, EF должен создавать только все экземпляры один раз. – Nullius
Да, он создает все экземпляры одновременно. На самом деле это проблема. Позвольте мне снова объяснить эту проблему. Скажем, у меня есть экземпляр продукта с экземпляром ProductType внутри него. Предположим, что экземпляр Product уже сохраняется в прошлом. Когда я пытаюсь обновить экземпляр Product, EF создает дубликат экземпляра ProductType (который не подходит для случая), если я не устанавливаю состояние атрибута ProductType в Unchanged. – Furkan