Come posso fare riferimento a una proprietà come ForeignKey collegata a un campo calcolato da DB (da una vista)?
Ho il seguente:
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; }
//...
}
Ogni volta che provo ad aggiornare una Person
, ottengo la seguente escpetion:
Messaggio:
Una proprietà dipendente in un ReferentialConstraint è mappata a una colonna generata dal negozio. Colonna: 'MainPersonSiteId'. Traccia dello stack:
a System.Data.Entity.Core.Mapping.Update.Internal.UpdateCompiler.BuildSetClauses (DbExpressionBinding target, PropagatorResult row, PropagatorResult originalRow, TableChangeProcessor processor, Boolean insertMode, Dictionary`2 & outputIdentifiers, DbExpression e return, Boolean e rowMustBeTouched) su System.Data. Entity.Core.Mapping.Update.Internal.UpdateCompiler.BuildUpdateCommand (PropagatorResult oldRow, PropagatorResult newRow, processore TableChangeProcessor) su System.Data.Entity.Core.Mapping.Update.Internal.TableChangeProcessor.CompileCommands (ChangeNode changeNode, UpdateCompiler compiler)
Nel database, che è Sql Server 12, Person proviene da una vista, in cui MainPersonSiteId viene proiettato da una funzione. Questo è un campo calcolato, che non ha bisogno di essere aggiornato dall'ORM.
Come definirlo con EntityFramework?
MODIFICARE :
Sono appena riuscito a far funzionare l'aggiornamento impostando DatabaseGeneratedOption.Identity
invece di DatabaseGeneratedOption.Computed
, tuttavia ho appena trovato che gli inserti erano ancora danneggiati. Così ho testato gli inserti con DatabaseGeneratedOption.Computed
e ... ha funzionato: /
La situazione è:
- Posso inserire solo con DatabaseGeneratedOption.Computed
- Posso aggiornare solo con DatabaseGeneratedOption.Identity
È strano come MSDN dice che DatabaseGeneratedOption.Computed
consente al DB di generare un valore per entrambi gli inserti e gli aggiornamenti mentre DatabaseGeneratedOption.Identity
fa solo per gli inserimenti
Le colonne nel database definite come IDENTITY sono diverse da quelle COMPUTATE.
Quando si inserisce una nuova riga, il motore di database crea un nuovo valore (numero) per una colonna IDENTITY. Ad esempio è possibile utilizzare questo come una colonna chiave primaria / unica. Non è possibile aggiornare una colonna IDENTITY. Non è possibile definire una formula per eseguire calcoli.
Quando vuoi calcolare qualcosa a livello di tabella, puoi usare le colonne calcolate. Qui devi definire una formula. Quando si crea la colonna calcolata con l'opzione PERSISTED, SQL-Server memorizza i valori calcolati nella tabella. Quando aggiorni le colonne che fanno parte di una colonna calcolata, solo la colonna calcolata viene aggiornata. Le colonne calcolate PERSISTED possono far parte di colonne-chiave-indice e chiavi esterne. Quando non si utilizza l'opzione PERSISTED, il database non memorizza i valori calcolati. Quindi deve fare il calcolo ogni volta che una query ha bisogno della colonna calcolata.
Quando aggiorni una riga, assicurati che la colonna calcolata non faccia parte dell'elenco di colonne da aggiornare (nella clausola SET di un'istruzione UPDATE).
È possibile definire i CHIAVI ESTERI solo tra tabelle e non viste.