2017-01-11 9 views
1

私はCRUD操作を行うためにEF6コードファースト(既存のデータベースから)を使用しています。私はいくつかのコピーライトの問題のために実際のコードを貼り付けることができないので、ここで説明するモックコードを書くつもりです。私はCRUD操作を行うための一般的なリポジトリを持ってEF6 - SaveChanges()のエンティティプロパティを条件付きで更新する

public partial class Person : EntityBase 
{ 
    public long Id { get; set; } // ID (Primary key) 
    public string LastName { get; set; } // LastName (length: 50) 
    public string FirstName { get; set; } // FirstName (length: 50) 
    public string SocialSecurity { get; set; } // SocialSecurity (length: 50) 
    public long CreatedById { get; set; } // CreatedByID 
    public System.DateTime CreatedDate { get; set; } // CreatedDate 
    public long UpdatedById { get; set; } // UpdatedByID 
    public System.DateTime UpdatedDate { get; set; } // UpdatedDate 
    public byte[] TimeStamped { get; set; } // TimeStamped (length: 8) 
} 

: はここに私の実体です。

public class Repository<T> : IRepositoryAsync<T> where T : class, IObjectState 
{ 
    private readonly IDataContextAsync context; 
    private readonly DbSet<T> dbSet; 
    //private read-only IUnitOfWorkAsync uow; 

    public Repository(IDataContextAsync _context) 
    { 
     context = _context; 
     dbSet = ((DbContext)context).Set<T>(); 
    } 

    public virtual IDataContextAsync Context { get { return context; } } 
    public IDbSet<T> DbSet { get { return dbSet; } } 
    public T FindOne(Expression<Func<T, bool>> predicate) 
    { 
     return dbSet.SingleOrDefault(predicate); 
    } 
    public IQueryable<T> FindBy(Expression<Func<T, bool>> predicate) 
    { 
     return dbSet.Where(predicate); 
    } 
    public void Add(T entity) 
    { 
     //entity.ObjectStateEnum = ObjectStateEnum.Added; 
     dbSet.Add(entity); 
    } 
    public void Delete(dynamic id) 
    { 
     var entity = dbSet.Find(id); 
     Delete(entity); 
    } 
    public void Update(T entity) 
    { 
     //entity.ObjectStateEnum = ObjectStateEnum.Modified; 
     dbSet.Add(entity); 
    } 
} 

ここに私のUnitOfWorkの実装があります。ここでも、コードフラグメントは単なるフラグメントです。完全なコードではありません。

public class UnitOfWork : IUnitOfWorkAsync 
{ 
    private IDataContextAsync context; 
    private IOperationStatus opStatus; 
    private Dictionary<string, dynamic> repositories; 
    private ObjectContext objectContext; 
    private DbTransaction transaction; 
    private bool disposed; 

    public IDataContextAsync DataContext { get { return context; } } 

    //public UnitOfWork() 
    //{ 
    // context = new RedStoneDbContext(); //???? _context; 
    // opStatus = new OperationStatus(); //???? _opStatus; 
    // repositories = new Dictionary<string, dynamic>(); 
    //} 
    public UnitOfWork(IDataContextAsync _context, IOperationStatus _opStatus) 
    { 
     context = _context; 
     opStatus = _opStatus; 
     repositories = new Dictionary<string, dynamic>(); 
    } 

    public IOperationStatus SaveChanges() 
    { 
     opStatus.Success = false; 
     try 
     { 
      int numRec = context.SaveChanges(); 
      opStatus.Success = true; 
      opStatus.RecordsAffected = numRec; 
     } 
     catch (SystemException ex) 
     { 
      opStatus = opStatus.CreateFromException(ex); 
     } 
     return opStatus; 
    } 
    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    public virtual void Dispose(bool disposing) 
    { 
     if (disposed) 
      return; 

     if (disposing) 
     { 
      try 
      { 
       if (objectContext != null && objectContext.Connection.State == ConnectionState.Open) 
        objectContext.Connection.Close(); 
      } 
      catch (ObjectDisposedException) 
      { 
       // do nothing 
      } 
      if (context != null) 
      { 
       context.Dispose(); 
       context = null; 
      } 
     } 
     disposed = true; 
    } 
    public IRepository<T> Repository<T>() where T : class, IObjectState 
    { 
     return RepositoryAsync<T>(); 
    } 

    public async Task<IOperationStatus> SaveChangesAsync() 
    { 
     opStatus.Success = false; 
     try 
     { 
      int numRec = await context.SaveChangesAsync(); 
      opStatus.Success = true; 
      opStatus.Message = "Record successfully saved!"; 
      opStatus.RecordsAffected = numRec; 
     } 
     catch (DbUpdateConcurrencyException ex) 
     { 
      opStatus = opStatus.CreateFromException(ex); 
     } 
     catch (SystemException ex) 
     { 
      opStatus = opStatus.CreateFromException(ex); 
     } 
     return opStatus; 
    } 
} 

ここに私の質問があります。 savechangesが呼び出されると、エンティティに「SocialSecurity」という列が含まれているかどうかを確認したい場合は、そのユーザーの役割と権限を調べます。すべてがOKならば、着信SSNをDBに残すようにします。もしそうでなければ、単にSaveChangesがSocialSecurityプロパティを無視するだけで、他のものはいつものように更新したいと思う。私はこれを行うための簡単かつ効率的な方法を理解することはできません。どんな助けも高く評価されます。

babu。

+0

確かに可能です。しかし、 'SaveChanges()'はこの種のロジックのための場所ではありません。 – haim770

答えて

0

ここでは、必要なアクションの論理的な推論をすべて行っています。ロジック自体を置く場所だけでなく、実行する必要があります。

クライアントコードがデータを取得するために呼び出すタイプ、関連するもの、フィルタされたものなど、ある種のサービスが必要です。リポジトリ経由でデータベースのIQueryableへの直接呼び出しは許されません。あなたがそれらを実装しているかどうかにかかわらず、あなたのコードから。

これらのサービスをお持ちの場合は、SocialSecurityに参加しているすべてのアクセス許可を直接確認できます。 また、SocialSecurityを定義するInterfaceを作成し、すべてのエンティティを適切にマークすることができます。 いずれにしても、該当する場合はロールチェックを実行できます。

役割チェックが失敗した場合は、ストレージから現在のエンティティをロードする必要があり、どちらかになります。

は、ストレージからロードされたものと、現在開催されたエンティティのSocialSecurityプロパティを交換してください。

それとも

更新(SocialSecurity値を除く)新たにロードされたエンティティ

内のすべての関連するプロパティは、今、あなたはアップデート(エンティティ)を実行することができます。

Update操作の背後にロジックがあり、権限が与えられていれば直接保存するか、現在の(ストレージから)SocialSecurity値を使用して保存する必要があります。変更されたもの。

しかし、考えてみると、これを逆転させることができ、ページの読み込み時に権限がない場合でも、ユーザーはSocialSecurity値を編集できなくなります。 通常、権限を持たないユーザーにデータを表示したり、編集の印象を与えるのは悪い習慣です。 これは問題を処理するより良い方法かもしれません。

+0

あなたの返事をありがとう。ユーザーが適切な権限を持っていない場合、フロントエンドにSSNの編集を禁止する適切な仕組みがあります。しかし、われわれ全員が知っているように、クライアントからのデータを盲目的に信頼することはできません。クライアントの検証が有効であっても、サーバーは検証する必要があります。 –

+0

あなたは本当にそこに正しいです、私はそれが更新を防ぐのに十分であることを意味していなかった、ちょうどクライアントフレンドリーである。 SSNを含まない(アクセス許可が指示されている)使用する別のビューモデルを作成し、それを使用して毎回完全にロードされたモデルをストレージから更新することもできます。乾杯。 –

+0

ご返信ありがとうございます。答えは私の問題に適用可能な解決策を提供していませんが、私は問題にどのようにアプローチできるかについて私にいくつかの考えを与えました。他の誰もより良い解決策で答えてくれていないので、私はあなたの答えを受け入れたものとしてマークしています。 –