Adding and updating entities with Entity Framework

后端 未结 2 1355
栀梦
栀梦 2021-02-04 15:00

In my last project I have used Entity Framework 5 Code First. I completed my project but had a lot of pain during the development process.

I tried to explain my pain bel

相关标签:
2条回答
  • 2021-02-04 15:39

    You can replace your code by:

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

    The reason why this is the same (unless the related entities were already attached to the context in another state than Unchanged before) is that Attach puts entity including all related entities in the object graph into the context in state Unchanged. Setting the state to Modified afterwards for entity only changes the state of the product alone (not the related entities) from Unchanged to Modified.

    0 讨论(0)
  • 2021-02-04 16:00

    Ok, you're just doing something wrong then. In addition to my comment, I've created a sample for your which shows that EF doesn't create duplicates by default.

    I have two classes:

    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; }
    }
    

    One context:

    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);
        }
    }
    

    Then one initializer class (this could inherit from other strategies if you want):

    public class InitDb<TContext> : DropCreateDatabaseAlways<TContext>
        where TContext : DbContext
    {
    }
    

    The main program:

        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));
        }
    

    This results in the following console output:

    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!
    

    Also, when looking in SQL Server Management Studio, this solution has only created (and updated) one product and one category.

    Ofcourse, you should work with repositories to retrieve, update and delete your data and a unit of work. These have been left out of the example.

    So, if you do not post any code, we can't help you much further :-)

    0 讨论(0)
提交回复
热议问题