2017-05-25 85 views
1

我有以下通用数据访问类,负责数据库操作。更新导航属性的通用数据访问层

internal sealed class DataStore<T> : IDataStore<T> 
    where T : BaseModel, new() 
{ 
    private readonly DataContext _context; 

    public DataStore(DataContext context) 
    { 
     this._context = context; 
    } 

    public async Task InsertNew(T obj) 
    { 
     await Task.Run(async() => 
     { 
      _context.Set<T>().Add(obj); 
      await _context.SaveChangesAsync(); 
     }); 
    } 

    public async Task<T> SelectObj(int id, Expression<Func<T, object>> includeExpression = null) 
    { 
     if (includeExpression != null) 
      return 
       await _context.Set<T>() 
        .Include<T, object>(includeExpression) 
        .FirstOrDefaultAsync(x => x.ID.Equals(id)); 

     return await _context.Set<T>().Where(x => x.ID.Equals(id)).FirstOrDefaultAsync(); 
    } 

    public async Task<List<T>> SelectAll(Expression<Func<T, object>> includeExpression = null) 
    { 
     if (includeExpression != null) 
      return await _context.Set<T>().Include<T, object>(includeExpression).ToListAsync(); 

     return await _context.Set<T>().ToListAsync(); 
    } 

    public async Task Update(T obj) 
    { 
     await Task.Run(async() => 
     { 
      var original = await SelectObj(obj.ID); 
      _context.Entry(original).CurrentValues.SetValues(obj); 
      await _context.SaveChangesAsync(); 
     }); 
    } 

    public async Task Delete(T obj) 
    { 
     await Task.Run(async() => 
     { 
      _context.Set<T>().Remove(obj); 
      await _context.SaveChangesAsync(); 
     }); 
    } 

    public async Task Delete(int id, Expression<Func<T, object>> includeExpression = null) 
    { 
     await Task.Run(async() => 
     { 
      var obj = await SelectObj(id, includeExpression); 
      await Delete(obj); 
     }); 
    } 
} 

Update功能的问题是,它只能通过更新,而不是对象的导航性能通过了T对象。

我已经尝试了以下,但我卡住,不知道我需要如何继续在这里。

private void GetNavProperties(T obj) 
    { 
     var objType = obj.GetType(); 
     foreach (var prop in objType.GetProperties()) 
     { 
      if (prop.PropertyType.IsClass) 
      { 
       var values = prop.GetValue(obj); 
       //How do I go further here, setting the Entity on the context 
      } 
     } 
    } 
+0

我知道我不会回答你的问题,而是扔在作品扳手......你会做更新...如果它只是'等待_context.SaveChangesAsync();'提供T obj最初是从上下文中拉出来的。 – Seabizkit

回答

0

玩过后,我结束了以下解决方案,为我的应用程序工作。

下面是解决方案,并附有解释其功能的注释。

private async Task UpdateNavProperties(T original, T newObject) 
    { 
     await Task.Run(async() => 
     { 
      //get type of object 
      var objType = original.GetType(); 

      //loop through properties on the Type 
      foreach (var prop in objType.GetProperties()) 
      { 
       //Check that property is a class/reference type, and not part of the System namespace 
       //string would be part of the system namespace, but my custom class not 
       if (prop.PropertyType.IsClass && !prop.PropertyType.Namespace.Equals("System")) 
       { 
        //get the old value 
        var oldValue = prop.GetValue(original); 
        //get new value 
        var newValue = newObject.GetType().GetProperty(prop.Name).GetValue(newObject); 
        //update the value 
        _context.Entry(oldValue).CurrentValues.SetValues(newValue); 
        //save changes 
        await _context.SaveChangesAsync(); 
       } 
      } 
     }); 
    } 

,并使用它,我做了以下内容:

public async Task Update(T obj, Expression<Func<T, object>> includeExpression = null) 
    { 
     await Task.Run(async() => 
     { 
      var original = await SelectObj(obj.ID, includeExpression); 
      _context.Entry(original).CurrentValues.SetValues(obj); 
      await _context.SaveChangesAsync(); 

      await UpdateNavProperties(original, obj); 
     }); 
    } 
+0

由于这是一种通用方法,因此即使未缩进,它也会始终更新导航属性。 1)如果您只需要更新Parent,请考虑这种情况。 此外,你也可以删除多个savechanges()它会破坏事务,并可能会影响部分保存在数据库中,如果发生错误。 – Eldho

+0

为了让其他用户阅读本文,我将修改解决方案,但对于我的示例,我总是需要它来更新导航属性。我同意SaveChanges(),忘记了这一点。感谢您的意见 –