Ok, stai solo facendo qualcosa di sbagliato allora. Oltre al mio commento, ho creato un esempio per il tuo che mostra che EF non crea duplicati per impostazione predefinita.
ho due classi:
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; }
}
un contesto:
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);
}
}
Poi una classe di inizializzazione (questo potrebbe ereditare da altre strategie se si vuole):
public class InitDb<TContext> : DropCreateDatabaseAlways<TContext>
where TContext : DbContext
{
}
I programma principale:
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));
}
Il risultato è il seguente output della console:
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!
Inoltre, quando si cerca in SQL Server Management Studio, questa soluzione ha creato solo (e aggiornato) un prodotto e una categoria.
Ovviamente, dovresti lavorare con gli archivi per recuperare, aggiornare ed eliminare i tuoi dati e un'unità di lavoro. Questi sono stati lasciati fuori dall'esempio.
Quindi, se non pubblicare alcun codice, non possiamo fare molto di più :-)
È possibile aggiungere il codice in cui si creano i dati? Se i tuoi riferimenti nelle classi sono corretti, EF dovrebbe creare tutte le istanze una sola volta. – Nullius
Sì, crea tutte le istanze contemporaneamente. Questo è il problema in realtà. Lascia che ti spieghi di nuovo il problema. Supponiamo di avere un'istanza di prodotto che contiene un'istanza ProductType al suo interno. Supponiamo che l'istanza del prodotto sia già persistente in passato. Quando provo ad aggiornare l'istanza di Product, EF crea un'istanza ProductType duplicata (che è un caso che non desidero) se non si imposta lo stato dell'attributo ProductType su Unchanged. – Furkan