2011-01-31 7 views
1

どのようにしてlinq2sqlを使ってコンパイル時に型を知らなくてもレコードを取得できますか?graq linq to primarykey by typeを知らなくても

は、これまでのところ、私は

Sub Delete(ByVal RecordType As String, ByVal ID As Integer) 
    Dim dummy = Activator.CreateInstance(MyAssembly, RecordType).Unwrap 
    Dim tbl = GetTable(dummy.GetType) 
    tbl.DeleteOnSubmit(dummy) 
End Sub 

を持っているが、もちろんダミーとして実際のレコード、私が直接SQL(またはexecutecommand)を使用したくない

そのわずかダミーではありませんデータコンテキスト部分クラスの削除時にビジネスロジックが進行しています

これは何とかできますか?

ありがとうございます! striplinwariorに応答して

EDIT

、私はに私のコードを編集した:これは削除コードcorrecltyをオフに解雇し、だけでなく、最初にレコードを追加しようとしているようだ

Sub Delete(ByVal RecordType As ObjectType, ByVal ID As Integer) 
    Dim dummy = Activator.CreateInstance(ObjectType.Account.GetType.Assembly.FullName, RecordType.ToString).Unwrap 
    SetObjProperty(dummy, PrimaryKeyField(RecordType), ID) 
    Dim tbl = GetTable(dummy.GetType) 
    tbl.Attach(dummy) 
    tbl.DeleteOnSubmit(dummy) 
    SubmitChanges() 
End Sub 

db、私はいくつかの "not null"フィールドが空であることをsqlexceptionとしています。これはプライマリキーだけであるため、ダミーレコードについては真実です。だから、私は他のコードを(あなたが持っていたと思っていた何か)投稿してみました。

彼女私の現在のコード:

Function LoadRecord(ByVal RecordType As String, ByVal RecordID As Integer) As Object 
    Dim dummy = Activator.CreateInstance(AssemblyName, RecordType).Unwrap 
    Dim rowType = dummy.GetType 
    Dim eParam = Expression.Parameter(rowType, "e") 
    Dim idm = rowType.GetProperty(PrimaryKeyField(RecordType)) 
    Dim lambda = Expression.Lambda(Expression.Equal(Expression.MakeMemberAccess(eParam, idm), Expression.Constant(RecordID)), eParam) 
    Dim firstMethod = GetType(Queryable).GetMethods().[Single](Function(m) m.Name = "Single" AndAlso m.GetParameters().Count() = 2).MakeGenericMethod(rowType) 
    Dim tbl = GetTable(rowType) 
    Dim obj = firstMethod.Invoke(Nothing, New Object() {tbl, lambda}) 
    Return obj 
End Function 
Sub Delete(ByVal RecordType As String, ByVal RecordID As Integer) 
    Dim obj = LoadRecord(RecordType, RecordID) 
    Dim tbl = GetTable(obj.GetType) 
    tbl.DeleteOnSubmit(obj) 
    SubmitChanges() 
End Sub 

あなたは

答えて

4

私は考えることができる唯一の方法は、主キーを表すメンバーを把握するために、データベースのマッピングからモデル情報を使用することですありがとう:

Dim primaryKey = (From t In db.Mapping.GetTables() _ 
      Where t.RowType.Type = tableType _ 
      Let keyMember = (From dm In t.RowType.DataMembers where dm.IsPrimaryKey).FirstOrDefault() _ 
      Select keyMember.Member.Name).First() 

(私はここLinqPadを使用しています:私は、利用可能な、このマッピング情報を持っているSQLモデルに典型的なLINQを想定)

次に、リフレクションを使用して、作成したダミーアイテムのキーメンバーの値を設定します。その後、ダミーを削除しようとする前にテーブルにダミーを添付し、falseを2番目のパラメータとして渡して、現在の値を使用してオブジェクトを実際に更新しないようにLINQに指示します。ここから変わります。

tbl.Attach(dummy, false) 
tbl.DeleteOnSubmit(dummy) 
db.SubmitChanges() 

意味がありますか?

編集

あなただけのオブジェクトを削除している、あなたは必ずしもデータベースからレコードを取得する必要はありません。オブジェクトのID値を設定し、これを上記のようにコンテキストにアタッチすると、LINQ to SQLはデータベースから取得したものとして扱います。その時点で、DeleteOnSubmitを呼び出すと、そのオブジェクトの主キー値に基づいてSQL内にDELETEステートメントを構築するようにコンテキストに指示する必要があります。

ただし、削除以外の目的でオブジェクトを取得する必要がある場合は、そのオブジェクトのクエリを表す式を作成する必要があります。手動でクエリを書いていたのであれば、例えば、次のような何かを言う:

Dim eParam = Expression.Parameter(rowType, "e") 
Dim lambda = Expression.Lambda(Expression.Equal(Expression.MakeMemberAccess(eParam, idMember), Expression.Constant(ID)), eParam) 
:だから動的括弧内のラムダ式を構築するために

Dim obj = tbl.First(Function(e) e.Id = ID) 

を、あなたはこのような何かを行う可能性があります

次に、一般的なFirstメソッドを呼び出すためにリフレクションを使用する必要があります。

Dim firstMethod = GetType(Queryable).GetMethods().[Single](Function(m) m.Name = "Single" AndAlso m.GetParameters().Count() = 2).MakeGenericMethod(rowType) 
Dim obj = firstMethod.Invoke(Nothing, New Object() {tbl, lambda}) 
+0

hi。私はプライマリーキーフィールドの名前を取得する方法を知っています。そのiveは考え出した。しかし、一度そのフィールドの名前があると、どのようにレコードを取得するのですか?それが問題です。ありがとう。 –

+0

@Yisman:私の編集を参照してください。 – StriplingWarrior

+0

ありがとう!鉱山を参照してください:-) –