2017-10-29 4 views
1

をデータをフェッチするエンティティフレームワークのSQLQueryのための変数テーブル名を使用して、私は、エンティティフレームワーククラスに文字列のVARを変換したいが、私はどのように今ありません。 私は多くのことを検索しましたが、見つからなかったことができます何もは、エンティティクラスに

public JsonResult GetReports(string tbl) 
{ 
    using (Context db = new Context()) 
    { 
     // *** Problem is that tbl is string and I want to Cast tbl 
     //  to Users Class OR eny of my other Class 
     var result= db.Database.SqlQuery<tbl>("SELECT * FROM Users"); 
     return Json(new { data = result}); 
    } 
} 

public partial class Users 
{ 
    public int ID { get; set; } 
    public string Name { get; set; } 
    public string Family { get; set; } 
    public Nullable<bool> Gender { get; set; } 
    public string UserName { get; set; } 
    public string Password { get; set; } 
    public string Email { get; set; } 
    public string Mobile { get; set; }  
    public bool Deleted { get; set; } 
} 

を私はそのような何かをしたい方法の理由は、私はいくつかの動的な方法クレタ島にしたいされており、tblが私のテーブル名のいずれかとすることができる(文字列としてあなたが強くUsersのようなクラスを()命名した、弱いまたは動的なアプローチに頼るべき理由があってはならないことを考えると)

+0

tblは文字列です。私は動的メソッドを作成したいのですが、文字列としてテーブル名があります。文字列varableをユーザークラスに変換します。 –

+2

デフォルトではできません。文字列を受け取り、正しいクラスインスタンスを作成するスイッチ/ケース構造を作成することができます。しかし、あなたはあらかじめそれらを知る必要があります。 –

+0

@SamKuhmonenそれは悪い考えではありません私はそれについて前に考えていますが、それが良い解決策を持っているのだろうかと思っています –

答えて

1

包括的な方法

たとえば、DRYがデータアクセスコードを作成し、ロギング、計測、再試行、例外処理などの一般的なクロスカッティングの問題を引き起こす可能性がある汎用リポジトリクエリ機能を構築する必要がある場合は、 SqlQuery<T>汎用ラッパー:あなたがターゲットPOCO(この場合はUsers)の種類を示すために、ジェネリック型パラメータを使用して、そのように呼び出すことができます

public async Task<IEnumerable<T>> TypedQuery<T>(string myQuery) 
{ 
    try 
    { 
     using (var db = new DbContext(ConnString)) 
     { 
      return await db.Database 
       .SqlQuery<T>(myQuery) 
       .ToListAsync() 
       .ConfigureAwait(false); 
     } 
    } 
    catch (Exception ex) 
    { 
     // Log error here 
     // Consider if the query can be retried 
     // Consider whether the exception should be propogated or swallowed 
     // Should the return type extended to indicate success/failure 
     return Enumerable.Empty<T>(); 
    } 
} 

var repo = new MyRepo(); 
var myUsers = await repo.TypedQuery<Users>("SELECT Id, Name FROM Users"); 

利点は、myUsersが厳密に型指定されたコレクションであることです。理論的には

動的なアプローチ

あなたの元の質問に答えるためにType overload of SqlQueryを使用することが可能です。あなたが直接System.Typeに渡すことができますか、私はあなたがこのような、型に他のいくつかの主要な抽象化をマップすることができると思います:

private static readonly IReadOnlyDictionary<string, Type> MyTypeMap 
= new Dictionary<string, Type> 
{ 
    { "users", typeof(Users)}, 
    { "foo", typeof(Foo)}, 
    ... other type maps here 
}; 

public async Task<IEnumerable<object>> WeakQuery(string someType, string someQuery) 
{ 
    Type typeOfMyClass; 
    if (MyTypeMap.TryGetValue(someType, out typeOfMyClass)) 
    { 
     using (var db = new DbContext(ConnString)) 
     { 
      return await db.Database.SqlQuery(typeOfMyClass, someQuery) 
       .ToListAsync() 
       .ConfigureAwait(false); 
      // The problem now is that you get an untyped DbRawSqlQuery 
     } 
    } 
    return Enumerable.Empty<object>(); 
} 

問題はあなたがどちらかに必要があるだろうが弱い型付けのけれどもされています結果を再キャスト、またはなど、使用されたときに非常に脆弱なコードのために作るなる、ダイナミックで作業:

var repo = new MyRepo(); 
dynamic x = await repo.WeakQuery("users", "SELECT Id, Name, Gender FROM Users"); 
Assert.IsNotNull(x); 
Assert.IsTrue(Enumerable.First(x).Name == "Foo"); 
  • SELECT *を避けるようにしてください - にマッピングするために、明示的にすべての列を選択し、代わりにUsersクラス。
+0

返信用tanx。私は前に試してポストを読むが、私はそれが私のために働いていないので、私は動的な方法を作成したいと思うので、線量を使用したくない一般的なクラスまたは何かのようなtbl varにする必要があります –

+0

これは私には意味がありませんあなたは強く、よく定義されたクラスの「ユーザー」を持っています。なぜ、どうしてあなたは動的になりたいのですか? 'SqlQuery 'は一般的なオーバーロードなので、自由に独自の汎用ラッパーを構築することができます。上記の動的な回避策のリンクは、他のオーバーロード、すなわち 'SqlQuery(Type、..) ' – StuartLC

+0

私の質問を更新しました。それを見てください –

関連する問題