我的任务是创建一个Windows服务,将数据从一个数据库转换并迁移到另一个数据库。我所从的数据库是由我们的一个子部门开发的,我对该数据库的结构没有发言权。
我的问题是,我所从的数据库存在一些内在的缺陷,我无法解决这些问题。最大的一个是,在许多表中,主键被设置为复合主键...这不是一个大问题,但其他应该关联的表只有一部分要引用的复合键。
例如,'人物'将ID和Surname作为复合键。 ID是代理自动增量整数键,Surname是varchar。仅ID列就足以唯一地标识一个人,但由于某种原因,他们还在复合键中包含了姓氏。 '项目'应该引用“人物”#39;表示项目被分配给谁......但是项目'只是拥有' PersonID',而不是姓氏。
我正在查看他们的数据库和Access前端,并且两者之间没有定义实际的关系....它只是通过他们的前端进行逻辑维护。
那么,如果我加入的表没有按照其他表的复合主键所指定的所有列,我该如何添加自己的导航属性?从技术上讲,我有ID号,这是我在逻辑上建立关联所需的全部内容,但是实体框架要求所有的复合键列都映射在引用约束中。
我可以忽略导航属性并让我的程序添加逻辑来弥补差距,但延迟加载意味着我必须分阶段构建我的查询。
如果复合键的列没有对表的标识做出有意义的贡献,是否有某种方法可以忽略它?
修改
我还应该注意,我永远不会写入他们的数据库。我只会查询他们的数据。我与之关联的用户帐户只被授予了选择权限。
答案 0 :(得分:1)
EF不必知道复合键。如果您确定某列是唯一的,那么您可以欺骗EF,只告诉它重要的关键字段。这需要一些工作。
当您正在对现有数据库进行操作时,我认为数据库优先方法最适合您。即便如此,还有很多工作要做,但我认为这在EDMX图表中比在手动键入的代码中更容易。
如果从数据库生成模型,首先要注意的是EF不会在EDMX中生成所有关联。这是因为EF只生成涉及数据库中整个密钥(除了密钥之外)的关联。
让我说明这是基于您的示例的高度简化的数据模型。从此数据模型生成EDMX模型后,该图如下所示:
Person
有一个复合键,Person
和Project
之间没有关联,尽管FK在数据库中。现在我们将在以下步骤中欺骗EF:
从主键中删除Person.name
:右键单击“名称”并取消选中“实体键”。
在Person
和Project
之间添加关联:右键单击Person
,选择Add New,Association ...填写如下所示的对话框:
请注意,未选中“添加外键属性...”。如果是,EF将添加新的PersonId1
字段。
手动定义外键:右键单击关联,然后选择“属性”。
在“属性”窗格中,单击“参照约束”右侧的省略号。
填写对话框:
现在图表应如下所示:
完成!
还是...?在构建项目或验证图表时,您将看到错误:
错误3003:从第74行开始映射片段时出现问题:EntitySet People的所有关键属性(People.Id)必须映射到表Person的所有关键属性(Person.Id,Person.Name)。 / p>
EF并不容易被愚弄。我们修改了概念模型。不是商店模式。 EF仍然知道Person
在数据库中有一个复合键。我们如何解决这个问题?不幸的是(或幸运的是?)在EDMX设计师中没有支持。我们必须编辑XML。
XML的第一部分包含SSDL content
,即存储架构定义。查找Person
的商店定义,它应该类似于:
<EntityType Name="Person">
<Key>
<PropertyRef Name="Id" />
<PropertyRef Name="Name" />
</Key>
<Property Name="Id" Type="int" StoreGeneratedPattern="Identity" Nullable="false" />
<Property Name="Name" Type="nvarchar" MaxLength="50" Nullable="false" />
</EntityType>
删除行
<PropertyRef Name="Name" />
现在欺骗已经完成,EF很高兴,模型验证了。
我必须承认我不喜欢这最后一部分。这是一个黑客,无论你怎么看待它。当您从数据库更新模型时,商店模型中所有这些经过仔细应用的修改都将消失。
如果您以代码优先工作,则不会出现此问题。您可以使用Entity Framework Power Tools或VS2013中新的集成“添加新模型”对话框从数据库重新设计模型,并手动添加所有关联并删除所有冗余密钥。我认为这项工作要多得多,但至少它是“更新安全的”。