作为 Entity Framework 6 中的外键的数据库计算属性

Posted

技术标签:

【中文标题】作为 Entity Framework 6 中的外键的数据库计算属性【英文标题】:Database computed property that is a foreign key in Entity Framework 6 【发布时间】:2016-05-28 21:11:39 【问题描述】:

我如何引用一个属性作为插入到数据库计算字段的 ForeignKey(从视图)?

我有以下:

public class PersonSite

    public int Id get;set;

    //...

    public int PersonId get;set;
    [ForeignKey("PersonId")]
    public virtual Person Person get;set;

    //...



public class Person

      public Id get;set;

      //...

      [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
      public int? MainPersonSiteId  get; protected internal set; 

      [ForeignKey("MainPersonSiteId")]
      [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
      public PersonSite MainPersonSite  get; protected internal set; 

      //...

每当我尝试更新 Person 时,我都会收到以下异常:

消息:

ReferentialConstraint 中的依赖属性映射到 商店生成的列。列:'MainPersonSiteId'。堆栈跟踪:

在 System.Data.Entity.Core.Mapping.Update.Internal.UpdateCompiler.BuildSetClauses(DbExpressionBinding 目标,PropagatorResult 行,PropagatorResult originalRow, TableChangeProcessor 处理器、布尔型 insertMode、Dictionary`2& outputIdentifiers, DbExpression& 返回, Boolean& rowMustBeTouched) 在 System.Data.Entity.Core.Mapping.Update.Internal.UpdateCompiler.BuildUpdateCommand(PropagatorResult oldRow、PropagatorResult newRow、TableChangeProcessor 处理器)在 System.Data.Entity.Core.Mapping.Update.Internal.TableChangeProcessor.CompileCommands(ChangeNode changeNode, UpdateCompiler 编译器)

在 Sql Server 12 的数据库中,Person 来自一个视图,其中 MainPersonSiteId 是从一个函数投影的。这是一个计算字段,不需要由 ORM 更新。

如何用 EntityFramework 定义它?

编辑:

我只是通过设置DatabaseGeneratedOption.Identity 而不是DatabaseGeneratedOption.Computed 设法使更新工作,但是我发现插入仍然损坏。所以我用DatabaseGeneratedOption.Computed 测试了插入,它......工作了:/

情况是: - 我只能插入 DatabaseGeneratedOption.Computed - 我只能使用 DatabaseGeneratedOption.Identity 进行更新

奇怪的是MSDN saysDatabaseGeneratedOption.Computed 让数据库为插入和更新生成一个值,而DatabaseGeneratedOption.Identity 只为插入生成一个值

【问题讨论】:

你能在数据库中做到这一点吗?您可以从计算列创建外键吗?如果您不能在数据库中执行此操作,我怀疑您可以使用 EF 执行此操作。如果你能做到,请展示一下。 @JotaBe,感谢您的评论。我认为 DatabaseGeneratedOption 只是说该属性是由数据库以某种方式处理的。引用自 MSDN,DatabaseGeneratedOption.Computed 的意思是:“数据库在插入或更新行时生成一个值。”而已。 EntityFramework 不应触及该字段。 EF 肯定会触及该字段来处理 FK。而且我认为您无法在数据库中创建该 FK。你可以吗?您如何期望 EF 做一些无法做到的事情? 【参考方案1】:

数据库中定义为 IDENTITY 的列与 COMPUTED 不同。

当您插入新行时,数据库引擎会为 IDENTITY-Column 创建一个新值(数字)。例如,您可以将其用作主/唯一键列。您不能更新 IDENTITY 列。您无法定义用于计算的公式。

当您想在表级别计算某些内容时,您可以使用计算列。在这里,您必须定义一个公式。当您使用 PERSISTED 选项创建计算列时,SQL-Server 将计算值存储在表中。当您更新属于计算列的列时,只有计算列才会更新。 PERSISTED 计算列可以是索引键列和外键的一部分。 当您不使用 PERSISTED 选项时,数据库不会存储计算值。因此,每次查询需要计算列时,它都必须进行计算。

当您更新一行时,请确保计算的列不是要更新的列列表的一部分(在 UPDATE 语句的 SET 子句中)。

您只能在表之间而不是视图之间定义 FOREIGN KEY。

【讨论】:

以上是关于作为 Entity Framework 6 中的外键的数据库计算属性的主要内容,如果未能解决你的问题,请参考以下文章

一列用于 Entity Framework Core 中两个不同表的外键

Entity Framework Core fluent api一对多和一对一产生重复的外键

《Entity Framework 6 Recipes》翻译系列 -----第二章 实体数据建模基础之有载荷和无载荷的多对多关系建模 (转)

Entity Framework 6 GUID 作为主键:无法将值 NULL 插入列“Id”、表“FileStore”;列不允许空值

Entity Framework 5/6 中的可更新视图

Entity Framework Core 6.0 中的新功能介绍