3

我不确定这是否可行,但我在数据库中插入了很多实体,并且对于每个项目,它都有一个语言属性,它是一个实体。目前我为每个要插入的项目创建一个新的语言对象,但这只是为了测试,因为它会创建很多重复项。语言在数据库中应该是唯一的,并且应该只指向现有的语言记录,我能想到的唯一方法是为每个插入进行单独的服务调用以查找语言代码并获取现有语言的 id,这是很多开销。

有没有办法让它根据语言代码自动查找记录并使用该记录?

谢谢

4

3 回答 3

4

两者ObjectContextDbContext都有方法尝试从内存中的上下文中找到已加载的实体 - GetObjectByKeyforObjectContextFindfor DbContextLanguage使用这些方法可以避免从数据库中多次加载实体。

这两种方法都需要一个主键值作为输入参数来按键查找实体。本质上将这些方法视为访问将主键与实体对象相关联的内部字典。

现在,参考您的评论...

本质上是尝试匹配自定义值而不是 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实体LanguageCustomValue,只执行一次,并且不会Language在数据库中创建对象的副本。

于 2012-09-21T13:33:29.583 回答
1

不确定您在这里的确切含义,但如果它在插入期间,您通常会检查它是否存在,如果不存在则添加它。如果您插入一堆实体,您可以将语言存储在上下文中。不确定这是否是最好的解决方案。不要认为没有密钥就可以快速找到商店或上下文中的对象。根据您的语言实体的复杂性,您可以将上下文“语言”变量转换为 ToDictionary()并通过它来代替。

//'db' is your context here.
var languages = db.Languages.all();
myentity MyEntity = new MyEntity();
myentity.property1 = "mynewvalue1";

var newlang = new Language{ LanguageName= "newlanguagename"};
//language exists?
if (!languages.Any( u => u.LanguageName== newlang.LanguageName ))
 {

  // no:
  db.Languages.InsertOnSubmit(newlang);
  db.SubmitChanges();
  myentitly.Language = newlang;
 }
else{

  //yes:
  myentitly.Language = languages.Where( u => u.LanguageName== newlang.LanguageName).Single();
 }

db.MyEntities.InsertOnSubmit(myentity);
db.SubmitChanges();
于 2012-09-26T23:22:57.477 回答
1

由于您关心开销性能成本,我建议这是处理此问题的最有效方法:

第 1 步:确保您的语言表是正确的。

我不确定您是如何定义使用哪些语言的,所以在这里我无法为您提供帮助,只需确保您的语言表包含所有需要的行。假设您的表格如下:

{ Id: 1 ; Language: "English" }
{ Id: 2 ; Language: "French"  }
{ Id: 3 ; Language: "German"  }

第 2 步:处理您的实体

步骤 2.1:创建一个Dictionary<string, int>以轻松映射您的语言表:

var lang_list = new Dictionary<string, int>();

using(var db = new DbContext()
{
     foreach(var row in db.Languages.ToList())
     {
            lang_list.Add(row.Language, row.Id);
     }
}

//From now on, you can refer to the local list.

步骤 2.2:向(待添加的)实体添加正确的语言

我不知道您将如何确定需要添加的语言。假设您有一个字符串变量myLanguage,其中包含您需要的语言的字符串名称。

您可能想要使用类似的东西:

int foundvalue;

if(lang_list.TryGetValue( myLanguage , out foundvalue ))
{
     //if language is in the list, the value (= the id of the row in the language
     // table) will be stored in foundvalue
     myEntity.LanguageId = foundvalue;
}
else
{
     //if the language wasn't found in the list, set a default lang (e.g. English)
     myEntity.LanguageId = 1;
}

我希望这可以帮助你解决你的问题?

使用此过程的好处:

  • 您只需为语言查询一次数据库。填充列表后,它将存储在内存中,这是一种性能更好的方法。
  • 如果实体设置了意外或不正确的语言,您将能够使用默认语言。
于 2012-09-27T12:32:21.527 回答