简体   繁体   中英

Database computed property that is a foreign key in Entity Framework 6

How can I reference a property to be a ForeignKey plugged to a DB computed field (from a view) ?

I have the following :

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; }

      //...
}

Whenever I try to update a Person , I get the following excpetion:

Message:

A dependent property in a ReferentialConstraint is mapped to a store-generated column. Column: 'MainPersonSiteId'. Stack trace:

at System.Data.Entity.Core.Mapping.Update.Internal.UpdateCompiler.BuildSetClauses(DbExpressionBinding target, PropagatorResult row, PropagatorResult originalRow, TableChangeProcessor processor, Boolean insertMode, Dictionary`2& outputIdentifiers, DbExpression& returning, Boolean& rowMustBeTouched) at System.Data.Entity.Core.Mapping.Update.Internal.UpdateCompiler.BuildUpdateCommand(PropagatorResult oldRow, PropagatorResult newRow, TableChangeProcessor processor) at System.Data.Entity.Core.Mapping.Update.Internal.TableChangeProcessor.CompileCommands(ChangeNode changeNode, UpdateCompiler compiler)

In the database, which is Sql Server 12, Person comes from a view, where MainPersonSiteId is projected from a function. This is a computed field, which does not need to be updated by the ORM.

How to define it with EntityFramework ?

EDIT :

I just managed to have update working by setting DatabaseGeneratedOption.Identity instead of DatabaseGeneratedOption.Computed , nevertheless I just found the inserts were still broken. So I tested the inserts with DatabaseGeneratedOption.Computed back and it ... worked :/

The situation is :
- I can insert only with DatabaseGeneratedOption.Computed
- I can update only with DatabaseGeneratedOption.Identity

It's strange as MSDN says that DatabaseGeneratedOption.Computed let the DB generate a value for both inserts and updates while DatabaseGeneratedOption.Identity does only for inserts

Columns in the database defined as IDENTITY are different from COMPUTED ones.

When you insert a new row, then the database engine creates a new value (number) for an IDENTITY-Column. For example you can use this as a primary/unique key column. You can not update an IDENTITY column. You can't define a formula for doing calculations.

When you want to calculate somethin' at the table level, you can use computed columns. Here you have to define a formula. When you create the computed column with the PERSISTED option, then SQL-Server stores the computed values in the table. When you update columns which are part of a computed column, only then the computed column gets updated. PERSISTED computed columns can be part of index-key-columns and foreign keys. When you don't use the PERSISTED option, the database does not store the computed values. So it has to do the calculation every time a query needs the computed column.

When you update a row, make sure the computed column is not part of list of columns to be updated (in the SET-clause of an UPDATE-statement).

You can define FOREIGN KEYs only between tables and not views.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM