との両方ObjectContext
にDbContext
、メモリ内のコンテキストからすでにロードされているエンティティを検索しようとするメソッドがありますGetObjectByKey
-forObjectContext
およびFind
for DbContext
。これらのメソッドを使用するとLanguage
、データベースからエンティティを複数回ロードすることを回避できます。
どちらの方法でも、エンティティをキーで検索するための入力パラメータとして主キー値が必要です。基本的に、これらのメソッドは、主キーをエンティティオブジェクトに関連付ける内部ディクショナリにアクセスするものと考えてください。
さて、あなたのコメントを参照してください...
基本的に、id /主キー値ではなく、カスタム値と一致させようとします。
...これらのメソッドは、検索する主キーの値を知っていることに依存しているため、使用できません。
私がすることは、主キーではなくエンティティに「カスタム値」を関連付ける独自のディクショナリによって、前述の内部ディクショナリのロジックを模倣することです。カスタム値はLanguage
テーブル内で一意であると想定しています。
したがって、アイデアは次のようになります。
このようなエンティティがあるとすると...
public class MyEntity
{
public int Id { get; set; }
public Language Language { get; set; }
public string SomeOtherValue { get; set; }
// ... more
}
public class Language
{
public int Id { get; set; } // primary key value
public string CustomValue { get; set; } // the unique custom value
// ... more
}
...そして、新しいエンティティを挿入するために使用しているデータのコレクションがあります...
public class Data
{
public string SomeOtherValue { get; set; }
public string LanguageCustomValue { get; set; }
// ... more
}
var dataList = new List<Data>
{
new Data { SomeOtherValue = "A", LanguageCustomValue = "EN" },
new Data { SomeOtherValue = "B", LanguageCustomValue = "FR" },
new Data { SomeOtherValue = "C", LanguageCustomValue = "EN" },
new Data { SomeOtherValue = "D", LanguageCustomValue = "EN" },
// ... more
}
...次に、これを使用できます:
using (var context = new MyContext())
{
var dict = new Dictionary<string, Language>();
foreach (var data in dataList)
{
Language language;
if (!dict.TryGetValue(data.LanguageCustomValue, out language))
{
// load the language only once from the database
language = context.Languages.SingleOrDefault(l =>
l.CustomValue == data.LanguageCustomValue);
dict.Add(data.LanguageCustomValue, language);
}
var myEntity = new MyEntity
{
SomeOtherValue = data.SomeOtherValue,
Language = language
};
context.MyEntities.Add(myEntity); // or AddObject
}
context.SaveChanges();
}
Language
これにより、ごとに1つのエンティティのみがロードされ、これは1回だけ実行され、データベース内LanguageCustomValue
にオブジェクトの複製は作成されません。Language