实体框架,TPT继承和多语言支持

时间:2010-10-12 14:45:55

标签: c# sql-server entity-framework ado.net

我有这个数据库结构:

服务

  • Id int PK
  • CategoryId FK
  • SomeOtherFields

LocalizedService

  • LocalizedServiceId PK
  • LanguageId FK
  • 名称
  • 描述

正如您所看到的,我有一个名为Service的基表和一个LocalizedService表,我在其中编写多语言数据,例如名称和描述,应该用不同的语言翻译。 我使用TPT继承在EF设计器中链接了两个表。 Service是LocalizedService的基类。问题是,TPT要求两个表都有主键,如果我使用的是1种语言就不会有问题,但我应该将服务行翻译成3种不同的语言。因此,只有LocalizedServiceId不应该是唯一的,但LocalizedServiceId + LanguageId的组合应该是唯一的,因为我无法在LocalizedService中插入多个语言行。例如,看看下面的LocalizedService行:

  • 1,1,SomeService,NULL< - Inserted
  • 2,1,AnotherService,NULL< - Inserted
  • 2,2,RussianTranslationService,NULL< - 无法插入,因为表中已存在值为2的LocalizedServiceId。

这不是DB方面的问题,我可以为多个字段创建PK(例如,LocalizedServiceId和LanguageId都将是主键),但在这种情况下,EF设计师会抛出错误说: “错误13错误75:密钥用法无效.uPay.Data.Entities.LocalizedServiceRecord无法定义密钥,因为其基类之一(uPay.Data.Entities.ServiceRecord)定义了密钥.D:\ Projects \ uPay \ uPay.Data .Entities \ Entities.edmx 1531 9 uPay.Data.Entities“。我真的需要尽快解决这个问题的解决方案,非常感谢您的帮助。

1 个答案:

答案 0 :(得分:2)

您从EDM获得的错误来自以下事实:EF在一对一关联上支持2个实体之间的TPT继承,这意味着数据库上的一对一关系,并且基本上要求两个表都具有主键。您的方案本质上是一对多关系,其中每个服务可以基于ServiceID和LocalizationID进行许多本地化。

顺便说一句, Craig Stuntz 在他的帖子here上建议了2种解决方法,第一种方法是深入到EDM的SSDL部分并从键部分:

<EntityType Name="ServiceTypeLocale">
   <Key>
       <PropertyRef Name="LocalizedServiceId" />
       <!-- You have to comment this:-->
       <!--<PropertyRef Name="LanguageId" />-->
   </Key>
...

这不是建议的方式,因为如果您这样做,那么从数据库更新模型向导将尝试在每次更新时“修复”您的映射。

另一种解决方法是在数据库中创建视图并模拟一对一关系,然后映射视图而不是ServiceLocalization表。