entity framework - side - EF 4.1: diferencia entre.WithMany() y.WithOptional()?
entity framework one to one (1)
A continuación hay dos configuraciones de API fluidas similares:
Con muchas()
modelBuilder.Entity<Country>()
.HasRequired(cou => cou.Currency)
.WithMany()
.WillCascadeOnDelete(false);
WithOptional ()
modelBuilder.Entity<Country>()
.HasRequired(cou => cou.Currency)
.WithOptional()
.WillCascadeOnDelete(false);
Lo que estoy tratando de expresar aquí es: cada Country
requiere una Currency
concreta, pero una Currency
puede tener cero, uno o muchos países asignados.
¿Cuál de las declaraciones anteriores tendré que usar? O en otras palabras: ¿Cuál es exactamente la diferencia entre los .WithMany()
y .WithOptional()
?
Si su modelo se vería así:
public class Country
{
public int CountryId { get; set; }
public Currency Currency { get; set; }
}
public class Currency
{
public int CurrencyId { get; set; }
}
entonces ...
modelBuilder.Entity<Country>()
.HasRequired(cou => cou.Currency)
.WithOptional()
.WillCascadeOnDelete(false);
... crea una relación de clave externa en la base de datos donde CountryId
en la tabla Countries
es la clave principal y la clave externa de la tabla CurrencyId
de las Currencies
al mismo tiempo, por lo que la tabla Countries
tiene una sola columna CountryId
. Un registro de Currencies
puede vivir sin un registro de Countries
relacionado. Pero si un registro de Currencies
tiene un registro de Countries
relacionado Countries
entonces no más de uno porque la clave externa es CountryId
que es la clave principal al mismo tiempo y, por lo tanto, solo puede estar en un registro. Entonces, la relación Currencies -> Countries
es de 1-to-0...1
.
El otro ejemplo ...
modelBuilder.Entity<Country>()
.HasRequired(cou => cou.Currency)
.WithMany()
.WillCascadeOnDelete(false);
... crea una segunda columna CurrencyId
en la tabla Countries
de la base de datos que no admite nulos y es una clave externa a la CurrencyId
de la tabla de Currencies
. Así que aquí es posible que un registro de Currencies
no tenga un registro de Countries
relacionado o uno o más de uno porque la clave externa ahora es otra columna, no idéntica a la clave principal. Por lo tanto, más de una fila en la tabla Countries
puede tener la misma clave externa. La relación Currencies -> Countries
aquí es de 1-to-0...n
.
Editar
Si toma el siguiente código para los dos modelos configurados de forma diferente ...
Country country1 = new Country();
Country country2 = new Country();
Currency currency = new Currency();
country1.Currency = currency;
country2.Currency = currency;
context.Countries.Add(country1);
context.Countries.Add(country2);
context.SaveChanges();
... entonces funciona el segundo caso (.WithMany): obtenemos dos nuevos países y una moneda en la base de datos.
Sin embargo, un poco extraño es que en el segundo caso (.HasOptional) solo se almacena el primer País, el segundo simplemente se ignora. En realidad, esperaba obtener una excepción. No estoy seguro si eso tiene que ser considerado como un error.
Edit2
Cambiar el orden en el ejemplo anterior para ...
context.Countries.Add(country1);
context.Countries.Add(country2);
country1.Currency = currency;
country2.Currency = currency;
... arroja la excepción esperada en el caso ".HasOptional".