使用Entity Framework添加和更新实体

在我的上一个项目中,我使用了Entity Framework 5 Code First。 我完成了我的项目,但在开发过程中遇到了很多痛苦。

我试着解释下面的痛苦:

我的数据访问逻辑层有几个数据类,如Product,ProductCategory,Order,Company,Manufacturer等……每个类都有一些其他类的引用。 例如,Product实例具有ProductCategory属性。

在我的数据访问对象类的Add和Update方法中,我在上下文中将每个属性的状态(基本类型除外)设置为Unchanged或Modified。 下面是一些dao类的更新方法的一部分:

context.Entry(entity).State = System.Data.EntityState.Modified; if (entity.Category != null) context.Entry(entity.Category).State = System.Data.EntityState.Unchanged; if (entity.Manufacturer != null) context.Entry(entity.Manufacturer).State = System.Data.EntityState.Unchanged; foreach (var specificationDefinition in entity.SpecificationDefinitions) { context.Entry(specificationDefinition).State = System.Data.EntityState.Unchanged; foreach (var specificationValue in specificationDefinition.Values) { context.Entry(specificationValue).State = System.Data.EntityState.Unchanged; } } 

这段代码是这样的。 我的一些添加或更新方法大约有30行代码。 我认为我做错了什么,添加或更新实体应该不是那么痛苦但是当我没有设置对象的状态时,我要么在数据库中得到exception或重复的条目。 我是否真的必须设置映射到数据库的每个属性的状态?

您可以通过以下方式替换代码:

 context.Products.Attach(entity); context.Entry(entity).State = System.Data.EntityState.Modified; 

这是相同的(除非相关实体已经附加到另一个状态中的上下文而不是之前的Unchanged )是因为Attach包含对象图中所有相关实体的实体放入状态Unchanged的上下文中。 之后为entity将状态设置为Modified仅将产品的状态(不是相关实体)从UnchangedModified

好的,那你只是做错了。 除了我的评论之外,我还为您创建了一个示例,其中显示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 Products { get; set; } public DbSet ProductCategories { get; set; } public MyContext() : base("name=MyContext") { } public MyContext(string nameOrConnectionString) : base(nameOrConnectionString) { } protected override void OnModelCreating(DbModelBuilder modelBuilder) { Database.SetInitializer(null); // Table mappings modelBuilder.Entity().ToTable("Product"); modelBuilder.Entity().ToTable("ProductCategory"); base.OnModelCreating(modelBuilder); } } 

然后是一个初始化类(如果需要,可以inheritance其他策略):

 public class InitDb : DropCreateDatabaseAlways where TContext : DbContext { } 

主要方案:

  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(); 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时,此解决方案仅创建(和更新)一个产品和一个类别。

当然,您应该使用存储库来检索,更新和删除您的数据和工作单元。 这些已被排除在示例之外。

所以,如果您不发布任何代码,我们无法帮助您更多:-)