Sono nullable chiavi esterne ammessi in Entity Framework 4?
Domanda
Ho un problema l'aggiornamento di una chiave esterna in un'entità Entity Framework. Sto usando entità auto tracking e ho un'entità con alcuni rapporti in cui la chiave esterna è presente come una proprietà (una delle nuove caratteristiche di EF4) anche. La chiave (un intero) è contrassegnato come modalità Null e concorrenza fisso.
In particolare ho un'entità di allarme con una relazione molti a 0..1 relazione a un utente conferma. (Un utente può confermare diversi allarmi, ma un allarme può essere confermata solo da zero o uno degli utenti).
Le definizioni di entità (semplificato):
Alarm properties
Id Int32 non-nullable identity entity key
UserId Int32 nullable concurrency mode fixed
Alarm navigation properties
User 0..1 multiplicity
User properties
Id Int32 non-nullable identity entity key
Name String non-nullable
Nel mio un'entità autonoma di monitoraggio l'utente conferma id è generato automaticamente come Nullable proprio come previsto, se assegno un utente a un allarme già persistente e ApplyChanges correre, i tentativi di estensione di sé contesto di tracciamento per impostare il valore originale ( null) nel contesto EF (in ImpostaValore nelle estensioni contesto), ma salta silenziosamente che, poiché il ClrEquivalentType del EdmType è un Int32 non annullabile.
estensioneAuto-generated:
private static void SetValue(this OriginalValueRecord record, EdmProperty edmProperty, object value)
{
if (value == null)
{
Type entityClrType = ((PrimitiveType)edmProperty.TypeUsage.EdmType).ClrEquivalentType;
if (entityClrType.IsValueType &&
!(entityClrType.IsGenericType && typeof(Nullable<>) == entityClrType.GetGenericTypeDefinition()))
{
// Skip setting null original values on non-nullable CLR types because the ObjectStateEntry won't allow this
return;
}
}
int ordinal = record.GetOrdinal(edmProperty.Name);
record.SetValue(ordinal, value);
}
Quando l'EF poi tenta di aggiornare il mio allarme ottengo un OptimisticConcurrencyException perché costruisce una clausola WHERE nell'istruzione UPDATE dove utilizza 0 (zero) come l'utente originale valore di chiave esterna invece del corretto "è nullo". (La clausola WHERE è parte del meccanismo EF ottimistica concorrenza, dove i valori originali delle proprietà contrassegnati con modalità concorrenza "fisso" sono controllate agains le proprietà nel database).
sono le chiavi straniere Null / tipi primitivi non sono pienamente supportati in entità di auto monitoraggio per EF? In caso contrario, io sono costretto a usare le entità fittizie, invece di nulla o ci sono altre soluzioni?
Aggiorna Ho cercato di riprodurre il problema senza STE, ma EF pianura sembra gestire bene la concorrenza ottimistica per le chiavi esterne nullable, quindi questo è un problema di STE, non un problema di EF. C'è numerose questioni con enti indipendenti di monitoraggio, quindi non è sorprendente che ci sia un problema tecnico qui. Se trovo una soluzione che può essere implementato nello script STE T4 mi post qui.
Soluzione
Bill Huth ha postato una patch lavora a MSDN .
Altri suggerimenti
Sì, chiavi esterne nullable sono certamente consentiti. Noi li usiamo tutto il luogo. Non si mostra il database o il modello, quindi è difficile essere certi che cosa il problema potrebbe essere, ma suona come se Entity Framework non riesce a capire la chiave primaria di una delle tabelle coinvolte. Forse non si dispone di uno, forse perché uno di loro è una vista? Sto indovinando qui, perché non si danno molte informazioni su quello che stai facendo.