2010-08-18 753 views
9

Me he encontrado con un escenario en el que Entity Framework 4.0 no genera una asociación con una entidad respaldada por una tabla que tiene un índice único, y me pregunto por qué.¿Por qué EF 4 no genera asociación para relación FK con columna con índice único?

La configuración básica es la siguiente: Vamos a decir que tengo dos tablas en SQL Server 2008 R2 y una relación de clave externa:

CREATE TABLE [dbo].[User](
    [Id] [int] IDENTITY(1,1) NOT NULL, 
    [GroupId] [int] NULL, 
CONSTRAINT [PK_User] PRIMARY KEY CLUSTERED 
(
    [Id] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

CREATE TABLE [dbo].[Group](
[Id] [int] IDENTITY(1,1) NOT NULL, 
CONSTRAINT [PK_Group] PRIMARY KEY CLUSTERED 
(
    [Id] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, 
    ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

ALTER TABLE [dbo].[User] WITH CHECK ADD CONSTRAINT [FK_User_Group] 
    FOREIGN KEY([GroupId]) 
REFERENCES [dbo].[Group] ([Id]) 

Por otra parte, asumirá el siguiente índice está presente:

CREATE NONCLUSTERED INDEX [IX_Group] ON [dbo].[Group] 
(
[Id] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 

Si le digo al diseñador en Visual Studio 2010 que genere un Modelo de datos de entidad ADO.NET, obtengo un modelo con dos clases, User y Group, User que tiene una propiedad de navegación llamada Group. Eso está bien y bien.

Ahora, supongamos que en lugar de que el índice era la siguiente:

CREATE UNIQUE NONCLUSTERED INDEX [IX_Group] ON [dbo].[Group] 
(
    [Id] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 

Es decir, la cosa única que he hecho es hacer que el índice de un índice único. Una vez hecho esto, cuando le digo al diseñador de Visual Studio que genere un Modelo de Entidad, la asociación entre usuarios y grupos no aparece y el User no tiene propiedades de navegación. La inspección del archivo EDMX generado revela que el modelo de almacenamiento no tiene AssociationSet en absoluto.

¿Alguien puede explicar por qué es esto? ¿Por qué el índice único impide que EF modele la relación?

Gracias.

Respuesta

12

Un índice único permite 1 valor NULO, una clave principal no permite NULLS. ¿Cómo va a coincidir con el NULL cuando nada es igual a NULL ni siquiera otro NULL

+0

Hmm, tal vez tengas razón, pero Linq2SQL puede manejar esta situación. Además, puedo agregar los conjuntos de asociación apropiados, etc. en el EDMX a mano y funcionará bien, así que todavía no entiendo por qué EF se da por vencido. – Rune

+0

thnaks man mucho, perdí más de 1 hora investigando por qué las propiedades de navegación no están mapeando, tu respuesta me ayudó. gracias de nuevo –

1

Tengo el mismo problema. Sin embargo, en mi caso, la columna a la que intento vincular no es la clave principal. Por lo tanto, no funcionará. El archivo EDMX no compilará diciendo que tiene que vincular a una clave principal. Esto tiene sentido. La única razón por la que me encuentro con el problema es que estoy tratando con una base de datos heredada que fue mal diseñada.

Sin embargo, en su caso, está creando un índice único en una columna de identidad. ¿Por qué? Una columna de identidad está garantizada para ser única de todos modos. Además, es su clave principal la que tendrá un índice por defecto.

Encontré este enlace que explica que las asociaciones con restricciones únicas no son actualmente compatibles con EF, pero parece que lo están planeando para una versión futura.

http://blogs.msdn.com/b/efdesign/archive/2011/03/09/unique-constraints-in-the-entity-framework.aspx?wa=wsignin1.0&CommentPosted=true#commentmessage

+0

"Por supuesto, una columna de identidad está garantizada para ser única". No, no lo es. Los valores duplicados son posibles con 'SET IDENTITY_INSERT' o con' DBCC RESEED'. – hvd

+0

Uh, sí, pero tienes que salir de tu camino para hacerlo. Cuando haces eso, es intencional. –

+0

Respondí "De todos modos, una columna de identidad garantiza ser única."Eso significa que es imposible obtener valores duplicados, pero lo que ahora dice que realmente quiere decir es que es imposible obtener valores duplicados por accidente. Eso puede ser cierto (no estoy del todo seguro), pero es un reclamo mucho más débil, y si varias aplicaciones funcionan en la misma base de datos, significa que la suposición de que la columna es única puede no ser válida, porque otro usuario en otra aplicación puede haber insertado intencionalmente un valor duplicado que no esperaba. – hvd

Cuestiones relacionadas