0

エンティティ + ソリューションに含まれるプロパティを更新するための簡単なソリューションを見つけようとしています。DBContext (データベース) の汎用リポジトリを作成しました。親エンティティは更新されますが、子プロパティの変更は処理されません。これらの変更を処理または追跡する方法はありますか?

子プロパティを更新するためのサンプル コード: (コメントを見てください - サンプル コード)


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

ブランドサービス:


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

1 に答える 1

0

IObjectWithState インターフェイスと State 列挙型を作成して、変更を手動で追跡します。

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

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

マップされたすべてのエンティティにインターフェイスを実装します

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

状態を変換し、グラフ全体に変更を適用するために、次の 2 つのヘルパー メソッドを追加します。

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();
    }
于 2013-07-25T11:41:58.263 に答える