2017-01-11 19 views
1

Я использую первый код EF6 (из существующего db) для выполнения операций CRUD. Я собираюсь написать некоторый макет кода здесь, чтобы объяснить, потому что я не могу вставить реальный код из-за некоторых прав на копирование. Вот моя сущность:EF6 - Условно обновить свойство Entity на 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, но обновлял все остальное, как обычно. Я не могу понять простой и эффективный способ сделать это. Любая помощь высоко ценится.

Babu.

+0

Это, безусловно, возможно.Но, 'SaveChanges()' определенно не место для такого рода логики – haim770

ответ

0

У вас есть все логические аргументы в пользу необходимых действий здесь, это всего лишь вопрос, где вы ставите логику - и что вам нужно делать.

У вас должен быть какой-то Сервис для каждого типа, который клиентский код вызывает для извлечения данных, будь то связанный, отфильтрованный и т. Д. Прямые вызовы IQueryable базы данных через репозиторий не должны быть разрешены - я не могу сказать из вашего кода, если вы их реализуете или нет.

Если у вас есть эти Услуги, вы можете напрямую проверить разрешения для тех, кто имеет право на участие в SocialSecurity. В качестве альтернативы вы можете создать интерфейс, который определяет SocialSecurity, и соответствующим образом пометить все сущности. В любом случае вы можете выполнить проверку роли, если это применимо.

Если проверка роли не удается, вам нужно будет загрузить текущий объект из хранилища и либо:

Заменить свойство SocialSecurity на настоящее время находится лицо с одной загруженными из хранилища.

Или

Обновить все соответствующие свойства во вновь загруженного объекта (за исключением стоимости SocialSecurity)

Теперь вы можете выполнить обновление (юридическое лицо).

Для этого не существует короткого пути, существует логика операции обновления и его необходимо сохранить непосредственно (если разрешение предоставлено) или сохранить при сохранении текущего (из хранилища) значения SocialSecurity вместо любого изменил один.

Однако, думая об этом, вы можете инвертировать это и не разрешать пользователю изменять значение SocialSecurity вообще, если у них нет разрешения при загрузке страницы. Как правило, плохой практикой является отображение данных или предоставление им впечатления от редактирования пользователю, у которого нет разрешения на это. Это может быть лучший способ справиться с этой проблемой.

+0

Спасибо за ваш ответ. У меня есть надлежащий механизм на передней панели, чтобы запретить редактирование SSN, если у пользователя нет соответствующих разрешений. Но, как мы все знаем, мы не можем слепо доверять данным, поступающим от клиента. Сервер должен проверять, даже если у нас есть проверка клиента на месте. –

+0

Ты абсолютно прав, я не подразумевал, что этого было достаточно, чтобы предотвратить обновление, просто быть дружелюбным к клиенту. Вы также можете создать другую модель представления для использования, которая не включает SSN (когда диктуются разрешения), а затем использовать это, чтобы обновлять полностью загруженный из хранилища каждый раз. Приветствия. –

+0

Спасибо за ваш ответ. Хотя вы отвечаете, не предоставил подходящего решения моей проблемы, он дал мне некоторые идеи о том, как я могу подойти к проблеме. И поскольку никто больше не ответил с лучшим решением, я отмечаю ваш ответ как принятый. –

 Смежные вопросы

  • Нет связанных вопросов^_^