2017-12-06 7 views
1

テーブルにエンティティを挿入する方法があります。 Matcherプロパティ(Nameなど)に基づくテーブル。コードを実行すると、チェックラインに 'SQLへの変換はサポートされていません'がスローされます。私のコード部分は以下の通りです。この問題を解決するにはどうすればよいですか?Linq一般的な挿入メソッドを使用すると、SQLスローにSQL例外へのサポートされた変換がありません

public static InsertStatus Add<T>(T ent, string matcherProp) where T : class 
    { 
     System.Data.Linq.Table<T> t = otdc.GetTable<T>(); 

     //Exception on this line 
     if (t.Any(item => object.Equals(GetPropValue(item, matcherProp), GetPropValue(ent, matcherProp)))) 
      return InsertStatus.AlreadyExists; 

     try 
     { 
      t.InsertOnSubmit(ent); 
      otdc.SubmitChanges(); 
      return InsertStatus.Successfull; 
     } 
     catch 
     { 
      return InsertStatus.UnknownError; 
     } 
    } 
    public static object GetPropValue(object src, string propName) 
    { 
     return src.GetType().GetProperty(propName).GetValue(src, null); 
    } 
+0

GetPropValueをSQLに変換することはできません。 Linq-to-SQLプロバイダが理解できる 'Expression'が必要です。 –

答えて

2

実行時には、エクスプレッションツリーを作成する必要があります。幸いにも、これはあなたのケースではあまり難しくありません。 matcherPropをテストするメンバーの名前で、valは、などの既存の値です

p => p.{matcherProp} == {val} 

:何これが行うことのための論理ツリーを構築している

var p = Expression.Parameter(typeof(T), "p"); 
var val = GetPropValue(ent, matcherProp); 
var test = Expression.Lambda<Func<T, bool>>(
    Expression.Equal(
     Expression.PropertyOrField(p, matcherProp), 
     Expression.Constant(val) 
    ), p); 

if (t.Any(test)) 
    return InsertStatus.AlreadyExists; 

:それはようなものになります定数。そしてExpression.Constantに供給する - valnullであれば、あなたも財産(PropertyInfo.PropertyType)のタイプを供給することができない限り、あなたは、問題を取得する可能性があります

注意。


は編集:これを実行する別の方法は、定数としてentを供給することです:

var p = Expression.Parameter(typeof(T), "p"); 
var test = Expression.Lambda<Func<T, bool>>(
    Expression.Equal(
     Expression.PropertyOrField(p, matcherProp), 
     Expression.PropertyOrField(Expression.Constant(ent), matcherProp), 
    ), p); 

これは、その後にもっと似ている:

ラムダでentがはるかに振る舞う
p => p.{matcherProp} == ent.{matcherProp} 

「キャプチャされた変数」のように。

0

matcherPropを文字列にするのではなく、Expression<Func<T, P>>にすると、Add(myEntity, e => e.Name)と呼び出すことができます。

次に、あなたはもちろんの適切なエラーチェックで

public static InsertStatus Add<T>(T ent, Expression<Func<T,P>> keySelector) where P : class 
{ 
    System.Data.Linq.Table<T> t = otdc.GetTable<T>(); 

    var memberAccess = (keySelector as LambdaExpression)?.Body as MemberExpression; 
    ParameterExpression paramExpr = Expression.Parameter(typeof(T), "e"); 
    Expression<Func<T, bool>> predicate = Expression.Lambda<Func<T,bool>>(
      Expression.Equal(memberAccess.Update(Expression.Constant(ent)), memberAccess.Update(paramExpr)), paramExpr); 

    if (t.Any(predicate)) 
    { 

ようなものが必要。

関連する問題