2017-05-25 3 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

を...何を更新します...最初にT objが最初にコンテキストから取り出されたのであれば、'content.SaveChangesAsync();を待っていました。 – 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()を削除すると、トランザクションが中断され、何らかの問題が発生した場合にdb内に部分的な保存が行われます。 – Eldho

+0

この記事を他のユーザーに読んでもらうためにソリューションを変更しますが、私の例では常にNavigationプロパティを更新する必要があります。私はSaveChanges()に同意し、それを忘れてしまった。ありがとうコメント –

関連する問題