EF4.1: Possible to have zero-or-one to zero-or-one (0..1 to 0..1) relationship?
.NET 4.0 with SQL Server 2008 R2. I am trying to represent a 0..1 to 0..1 relationship and I keep getting the following error:
Error 113: Multiplicity conflicts with the referential constraint in Role '{0}' in relationship '{1}'. Because all of the properties in Dependent Role are non-nullable, multiplicity of the Principal Role must be '1'.
I get this message even when the properties in the depe开发者_如何学Cndent entity are nullable. Is it possible to represent this relationship in Entity Framework?
An example of when this might occur (independently of whether it is good database design to do so) is when you have a request that exists by itself, a result that becomes associated with it once the request is completed, and when the request is eventually pruned but the results all remain.
No it is not possible and I doubt it works in SQL server. Database relation requires that one end becomes dependent. It means that it references primary key (PK) of a principal end - we call this foreign key (FK). If we talk about one-to-one relation the FK must be marked as unique so that only one record in the dependent table can reference a given record from the principal table. The only valid relation in this case is 0..1 - 1 where principal can exist without dependent but the dependent can exist only when related to existing principal because its FK value must be set to PK value of the principal. Theoretically FK can be nullable but it depends on the way how database implements unique constraints. If the database counts null as another unique value only one dependent record can have FK set to null (I think this is a case of SQL server).
In EF this is even more complicated because EF doesn't support unique constraints and because of that you can build one-to-one relation only when FK in dependent entity is also its PK (= no way to set it to null). If you cannot set FK to null you cannot have it nullable and because of that principal entity must exists otherwise the referential integrity will throw error.
The best solution for you is considering Request
as principal entity and Result
as dependent. Request must be created first and it must be kept in the database as long as the Result
. Result
must have same PK value (the column cannot be auto incremented) as the corresponding Request
(and PK must be FK to Request
).
This was possible in a number of ways with SQL 2008 (e.g. filtered index, constraint on computed column) and is default functionality on unique index in SQL 2012.
According to the ANSI standards SQL:92, SQL:1999, and SQL:2003, a UNIQUE constraint should disallow duplicate non-NULL values, but allow multiple NULL values. SQL's support for this is somewhat recent, but not non-standard.
Note that just as a 0..1 to many relation can have zero of either and still be perceived as having a dependent column, so can a 0..1 to 0..1 relation.
Note that EF5 (newer than this this Ladislav's answer) also supports this, but the direction of the dependency is determined by the order in which the 0..1 is set in the design if you are using Model-First. However, it does still seem to be deterministic.
Yes, there is a way to do what you want: make both tables subtypes of another table. This means to synchronize their PK values so that the PK value of one table is equal to a corresponding PK value in another table. If for example both tables have separate identity
columns, they will both have to be changed to regular columns, the identity
generated elsewhere, and then the same value used in both tables when the two tables have a one-to-one relationship.
That is, create a supertype or "master" table that holds the PK value that will optionally be once in each of the other two tables. Make the key column of the two tables both the CLUSTERED PK of that table, and also an FK to the master table, not to the other subtype table.
The problem is solved. The tables can both have zero or one rows of each value.
Ultimately, if PK generation is not identity-based, and there is no data is stored in the supertype table besides the PK value, then in fact the supertype table isn't really needed, except in the case of definitively recording that the logical entity exists (it is in the supertype table) but has zero rows in both the subtype tables. If the absence of the value is enough to reliably indicate that both subtype tables have zero rows, and the PK value for the two tables can be generated without an identity column, then the supertype table can be disposed of. No FK between the two tables is actually needed, because either table is allowed to have no row matching a present row in the other table.
精彩评论