0

我試圖找到一個簡單的解決方案來更新實體+我的解決方案中包含的屬性。我爲我的DBContext(數據庫)創建了一個通用存儲庫。它會更新父實體,但不處理子屬性的更改。有沒有辦法處理或跟蹤這些變化?用於更新子屬性格式通用儲存庫EF 5 - 更新實體和它的複雜/標量/導航屬性

示例代碼:(看評論 - 示例代碼)


[HttpPut] 
    public HttpResponseMessage PutBrand(Brand brand) 
    { 
     if (!ModelState.IsValid) 
     { 
      return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState); 
     } 

     try 
     { 
      // example code 
      brand.BrandSizes.FirstOrDefault().Name = "I'm a Test"; 


      // add values 
      brand.State = State.Changed; 
      brand.DateChanged = DateTime.Now; 

      // update 
      brand = _brandService.UpdateBrand(brand); 
      // save 
      _brandService.SaveBrandChanges(); 
      // signalR 
      Hub.Clients.All.UpdateBrand(brand); 

      return Request.CreateResponse<Brand>(HttpStatusCode.OK, brand); 
     } 
     catch (Exception ex) 
     { 
      return Request.CreateResponse(HttpStatusCode.InternalServerError, ex.Message); 
     } 
    } 

語境:


public class ERPContext : DbContext 
{ 
    #region Catalog 

    public DbSet<Brand> Brands { get; set; } 

    public DbSet<BrandSize> BrandSizes { get; set; } 

    public DbSet<BrandSizeOption> BrandSizeOptions { get; set; } 

    public DbSet<BrandTierPrice> BrandTierPrices { get; set; } 

    #endregion Catalog 


    public ERPContext() 
     : base("db-erp") 
    { 
     Configuration.LazyLoadingEnabled = false; 
     Configuration.ProxyCreationEnabled = false; 
    } 



    protected override void OnModelCreating(DbModelBuilder modelBuilder) 
    { 

     modelBuilder.Conventions.Remove<PluralizingTableNameConvention>(); 


    } 
} 

通用存儲庫:


public class ERPRepository<T> : IRepository<T> where T : class 
{ 
    #region Fields 

    private DbSet<T> _dbSet; 
    private DbContext _dataContext; 

    #endregion Fields 

    #region Ctor 

    public ERPRepository(DbContext dataContext) 
    { 
     if (dataContext == null) 
     { 
      throw new ArgumentNullException("dataContext", "dataContext cannot be null"); 
     } 

     _dataContext = dataContext; 
     _dbSet = _dataContext.Set<T>(); 
    } 

    #endregion Ctor 

    #region Methods 

    public T Add(T item) 
    { 
     return _dbSet.Add(item); 
    } 

    public T Delete(T item) 
    { 
     return _dbSet.Remove(item); 
    } 

    public T Update(T item) 
    { 
     var updated = _dbSet.Attach(item); 
     _dataContext.Entry(item).State = EntityState.Modified; 
     return updated; 
    } 

    public IQueryable<T> Query(params Expression<Func<T, object>>[] includes) 
    { 
     var query = _dbSet; 

     if (includes != null) 
     { 
      includes.ToList().ForEach(x => query.Include(x).Load()); 
     } 

     return query; 
    } 

    public void SaveChanges() 
    { 
     _dataContext.SaveChanges(); 
    } 

    #endregion Methods 
} 

型號:


public class Brand 
{ 
    #region Ctr 

    public Brand() 
    { 
     BrandSizes = new List<BrandSize>(); 
     BrandTierPrices = new List<BrandTierPrice>(); 
    } 

    #endregion Ctr 

    #region Properties 

    public int Id { get; set; } 

    public string Name { get; set; } 

    public string Description { get; set; } 

    public int? LogoId { get; set; } 

    public int DisplayOrder { get; set; } 

    public bool Deleted { get; set; } 

    public bool Locked { get; set; } 

    public State State { get; set; } 

    public DateTime DateChanged { get; set; } 

    public DateTime DateCreated { get; set; } 

    #endregion Properties 

    #region Mapping 

    public virtual Picture Logo { get; set; } 

    public virtual List<BrandSize> BrandSizes { get; set; } 

    public virtual List<BrandTierPrice> BrandTierPrices { get; set; } 

    #endregion Mapping 
} 

BrandService:


public partial class BrandService : IBrandService 
{ 
    #region Fields 

    private readonly IRepository<Brand> _brandRepository; 
    private readonly IRepository<BrandSize> _brandSizeRepository; 
    private readonly IRepository<BrandSizeOption> _brandSizeOptionRepository; 

    #endregion Fields 

    #region Ctor 

    public BrandService(IRepository<Brand> brandRepository, IRepository<BrandSize> brandSizeRepository, IRepository<BrandSizeOption> brandSizeOptionRepository) 
    { 
     _brandRepository = brandRepository; 
     _brandSizeRepository = brandSizeRepository; 
     _brandSizeOptionRepository = brandSizeOptionRepository; 
    } 

    #endregion Ctor 

    #region Methods 


    public virtual IEnumerable<Brand> GetAllBrands() 
    { 
     return _brandRepository.Query(x => x.BrandSizes); 

     //return _brandRepository.Query(); 
    } 

    public virtual Brand GetBrandById(int id) 
    { 
     return _brandRepository.Query().Where(x => x.Id == id).FirstOrDefault(); 
    } 

    public virtual Brand InsertBrand(Brand brand) 
    { 
     return _brandRepository.Add(brand); 
    } 

    public virtual Brand UpdateBrand(Brand brand) 
    { 
     return _brandRepository.Update(brand); 
    } 

    public virtual Brand DeleteBrand(Brand brand) 
    { 
     return _brandRepository.Delete(brand); 
    } 

    public virtual void SaveBrandChanges() 
    { 
     _brandRepository.SaveChanges(); 
    } 



    #endregion Methods 
} 

回答

0

創建IObjectWithState接口和國家枚舉手動跟蹤變化:

public interface IObjectWithState 
{ 
    State State { get; set; } 
} 

public enum State 
{ 
    Added, 
    Unchanged, 
    Modified, 
    Deleted 
} 

和落實在每一個映射實體

public class Brand:IObjectWithState 
{ .... 
[NotMapped] 
    public State State { get; set; }} 

接口,並添加這兩種輔助方法的狀態轉換和應用在整個圖中的變化:

public static EntityState ConvertState(State state) 
    { 
     switch (state) 
     { 
      case State.Added : 
       return EntityState.Added; 
      case State.Deleted: 
       return EntityState.Deleted; 
      case State.Modified: 
       return EntityState.Modified; 
      case State.Unchanged: 
       return EntityState.Unchanged; 
      default: 
       return EntityState.Unchanged; 
     } 
    } 

    public static void ApplyStateChanges(this DbContext context) 
    { 
     foreach (var entry in context.ChangeTracker.Entries<IObjectWithState>()) 
     { 
      IObjectWithState stateInfo = entry.Entity; 
      entry.State = StateHelpers.ConvertState(stateInfo.State); 
     } 
    } 

當更新或插入任何對象編輯它的狀態是這樣object.State = State.Modified; ,然後修改您的插入或更新的方法是這樣的:

public void InsertOrUpdate(T entity, bool IsGraph) 
    { 
     if (((IObjectWithState)entity).State == State.Added) 
     { 
      dataContext.Entry(entity).State = System.Data.Entity.EntityState.Added; 
     } 
     else 
     { 
      dbset.Add(entity); 
      dataContext.Entry(entity).State = System.Data.Entity.EntityState.Modified; 
     } 
     //This method change the state of every changed object 
     if (IsGraph) 
      ApplyStateChanges(dataContext); 
     dataContext.Commit(); 
    } 
+0

THX @Anas爲應對如此之快。我想我得到的照片。你的意思是像這個網站的方法? [本網站示例](http://blog.longle.net/2013/05/11/genericizing-the-unit-of-work-pattern-repository-pattern-with-entity-framework-in-mvc/) – Nesse

+0

Thx @Anas。這正是我需要的。好的解決方案 – Nesse