我正在使用EF6代码优先(来自现有数据库)来执行CRUD操作。我将在这里写一些模拟代码来解释,因为由于一些版权问题我无法粘贴真实代码。 这是我的实体:
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时,我想看看实体是否包含一个列&#34; SocialSecurity&#34;如果有,我会查看用户的角色和权限。如果一切正常,想让传入的SSN持久存储在数据库中。如果没有,我只想让SaveChanges忽略SocialSecurity属性,但像往常一样更新其他所有内容。我无法找到一种简单有效的方法来做到这一点。任何帮助都非常感谢。
巴布。
答案 0 :(得分:0)
在这里,您拥有所需操作的所有逻辑推理,这只是您放置逻辑本身的位置 - 以及您需要做什么。
您应该为客户端代码调用以检索数据的每种类型提供某种服务,无论是相关的,已过滤的等等。不应允许通过存储库直接调用数据库的IQueryable - 我无法从你的代码是否正在实施。
如果您拥有这些服务,那么您可以直接检查任何与SocialSecurity有关的权限。 或者,您可以创建一个定义SocialSecurity的接口,并适当地标记所有实体。 无论哪种方式,您都可以在适用时执行角色检查。
如果角色检查失败,您需要从存储中加载当前实体,并且:
将当前持有的实体上的SocialSecurity属性替换为从存储中加载的属性。
或者
更新新加载的实体中的所有相关属性(SocialSecurity值除外)
现在您可以执行更新(实体)。
没有简短的方法可以做到这一点,更新操作背后有逻辑,它需要直接保存(如果授予权限),或保存,同时确保使用SocialSecurity值而不是任何更改当前(来自存储)之一。
但是,考虑到这一点,您可以将其反转,如果在加载页面时没有权限,则根本不允许用户编辑SocialSecurity值。 向没有权限的用户显示数据或给予编辑印象通常是不好的做法。 这可能是处理问题的更好方法。