2017-01-11 32 views
1

我使用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) 
} 

我有一個通用的倉庫做CRUD操作。

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」,如果存在,我查看用戶的角色和權限。如果一切正常,想要讓傳入的SSN保留在數據庫中。如果沒有,我只想讓SaveChanges忽略SocialSecurity屬性,但像往常一樣更新其他所有內容。我找不出一個簡單而有效的方法來做到這一點。任何幫助,高度讚賞。

巴布。

+0

這當然是可能的。但是,'SaveChanges()'絕對不是這種邏輯的地方 – haim770

回答

0

在這裏您已經具備了所有必要操作的邏輯推理,這只是您放置邏輯本身的位置以及您需要執行的操作。

對於客戶端代碼調用來檢索數據,相關,過濾等的每種類型,您都應該有某種服務。不應該允許通過存儲庫直接調用數據庫的IQueryable - 我無法分辨從你的代碼,如果你正在實施他們。

如果您擁有這些服務,那麼您可以直接檢查任何與SocialSecurity有關的權限。 或者,您可以創建一個定義SocialSecurity的界面,並適當地標記所有實體。無論哪種方式,您都可以在適用的情況下執行角色檢查。

如果角色檢查失敗,則需要從存儲和加載當前實體之一:

替換與從存儲加載一個已保存的實體SocialSecurity財產。

或者

更新中新加載的實體所有相關的屬性(除SocialSecurity值)

現在,您可以執行更新(實體)。

有沒有簡單的方法來做到這一點,有更新操作背後的邏輯,它需要直接保存(如果授予權限),或保存當前(從存儲)存儲SocialSecurity值而不是任何改變了一個。

但是,考慮一下,您可以反轉此操作,並且如果用戶在頁面加載時沒有權限,則不允許用戶編輯SocialSecurity值。 通常不好的做法是向沒有權限的用戶顯示數據或給予編輯印象。 這可能是解決問題的更好方法。

+0

感謝您的回覆。如果用戶沒有適當的權限,我在前端有適當的機制禁止編輯SSN。但是衆所周知,我們不能盲目信任來自客戶端的數據。即使我們有客戶端驗證,服務器也應該驗證。 –

+0

你在那裏絕對正確,我並不是暗示它足以阻止更新,只是客戶端友好。您還可以創建一個不同的視圖模型,以使用不包含SSN(當權限指定時),然後使用它來每次從存儲更新完全加載的視圖模型。乾杯。 –

+0

感謝您的回覆。雖然你的回答並沒有爲我的問題提供適用的解決方案,但它給了我一些關於如何解決問題的想法。由於沒有其他人用更好的解決方案來回答,我正在接受你的答案。 –

相關問題