Entity Framework POCO Обновить сущность?

Я пытаюсь сделать что-то очень, очень простое, но у Entity Framework, похоже, есть десятки способов сделать это, ни один из которых не работает.

У меня есть класс POCO, который я прочитал из базы данных, и я хочу обновить базу данных, внося изменения в этот класс. Это все, что я хочу сделать.

Вот что я пытаюсь: -

1) Мой класс POCO: -

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.Web.Mvc; // Needs project reference to System.Web.Mvc 3.0.0.0
using System.ComponentModel.DataAnnotations; // Needs project reference to System.ComponentModel.DataAnnotations 4.0.0.0

namespace Trust.Domain.Entities
{
    public class Product
    {
        [HiddenInput(DisplayValue=false)]
        public Int32 ProductID { get; set; }
        [Required(ErrorMessage = "Please enter a product name.")]
        public String Name { get; set; }
        [DataType(DataType.MultilineText)]
        public String Description { get; set; }
        public Decimal? PriceGuide { get; set; }
        public Decimal? PriceSold { get; set; }
        public Int32? HeightCM { get; set; }
        public Int32? WidthCM { get; set; }
        public Int32? DepthCM { get; set; }
        [Required(ErrorMessage = "Please enter a list of keywords. Seperate each with a comma.")]
        public String Keywords { get; set; }
        public String SKU { get; set; }
        public Int32 ProductStateID { get; set; }
    }
}

2) Мой контекст для обновления экземпляра этого класса POCO: -

using System; using System.Collections.Generic; using System.Linq;
using System.Text;

using Trust.Domain.Entities; using Trust.Domain.Abstract;

namespace Trust.Domain.Contrete {
    public class EFProductRepository : IProductRepository
    {
        private EFDbContext context = new EFDbContext();

        public IQueryable<Product> Products
        {
            get { return context.Products; }
        }

        public Product GetProduct(int productID)
        {
            Product product = context.Products.Where(p => p.ProductID == productID).FirstOrDefault();
            return product;
        }

        public void SaveProduct(Product product)
        {
            if (product.ProductID == 0)
            {
                context.Products.Add(product);
                context.SaveChanges();
            }
            else
            {
                //context.AttachTo("Product", product); 
                //var contactEntry = Context.ObjectStateManager.GetObjectStateEntry(product); 
                //contactEntry.ChangeState(EntityState.Modified); 
                //_context.SaveChanges();

                //var findProduct = GetProduct(product.ProductID); 
                //context.ApplyCurrentValues("Product", product); 
                //context.SaveChanges(); 

                context.Products.Attach(product);
                context.SaveChanges();

            }
        }

        public void DeleteProduct(Product product)
        {
            context.Products.Remove(product);
            context.SaveChanges();
        }
    }
}

3) EFDbContext определяется как:

using System; using System.Collections.Generic; using System.Linq;
using System.Text;

using System.Data.Entity; // Needs Entity Framework 4.1 project
reference. using System.Data.Entity.ModelConfiguration.Conventions;

using Trust.Domain.Entities;

namespace Trust.Domain.Contrete {
    public class EFDbContext : DbContext
    {
        #region " Overrides "

        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

            base.OnModelCreating(modelBuilder);
        }

        #endregion

        #region " Entities "

        public DbSet<Product> Products { get; set; }

        #endregion
    }
}

В подпрограмме SaveProduct я проверяю, не равен ли ProductID нулю. Если он не равен нулю, я пытаюсь обновить объект в базе данных. В этом коде я представляю три способа сделать это, которые я нашел повсюду. Первые два закомментированы, потому что они даже не компилируются, потому что члены, которые они используют, не существуют! Третий выглядит хорошо, работает и вообще не вносит изменений в базу данных.

Entity Framework — это очень большая, сложная и чрезмерно разработанная технология, поэтому существует множество способов сделать что угодно. Может кто-нибудь, пожалуйста, скажите мне, как обновить объекты моего продукта с учетом типа POCO и контекста на основе EFDbContext, который я создал. То, что я пытаюсь сделать, должно быть потрясающе простым, я не знаю, почему это не так.


person John Thompson    schedule 04.03.2012    source источник


Ответы (1)


Причина, по которой эти члены не существуют, заключается в том, что для EF существует два разных API: старый API ObjectContext и новый API DbContext. Эти первые два решения используют API ObjectContext, но вы используете API DbContext.

Проблема в том, что присоединяемый объект только прикрепит его, но пометит его как неизмененный, поэтому вам нужно пометить его как измененный, чтобы EF знал, что этот объект должен быть сохранен:

context.Products.Attach(product);
context.Entry(product).State = EntityState.Modified;
context.SaveChanges();

Первая строка в основном не нужна, потому что вторая все равно прикрепит сущность, если вы установите ее состояние как измененное, но мне нравится оставлять ее в коде, чтобы сделать это очевидным.

person Ladislav Mrnka    schedule 04.03.2012
comment
Спасибо Ладислав. Это решило это. Существует множество вариантов Entity Framework. Знаете ли вы какие-либо хорошие ресурсы, в которых точно указано, какие существуют варианты, чем они отличаются и как их использовать. Изначально EF был одной из замечательных идей Microsoft, но с тех пор они, похоже, все испортили. - person John Thompson; 05.03.2012
comment
Есть только два варианта. Проверьте эти две книги для DbContext API: Programming EF: Code First, Программирование EF: DbContext - person Ladislav Mrnka; 05.03.2012