2011-02-16 11 views
6

Tengo un problema con Pocos y claves externas con nulos. Tengo 2 tablas (pedidos y productos) cada tabla tiene una clave primaria compuesta (orderid, orderid2) y (productid, productid2) Y he establecido una asociación de 0.1 .. * entre las dos tablas. Una orden puede estar relacionada con 0 o 1 producto. Y un producto tiene * órdenes relacionadas con él.Excepción durante la corrección de asociación con claves externas compuestas que aceptan nulos

Cómo Crash:

  • crear un nuevo producto utilizando CreateObject().
  • Agregue el nuevo producto al conjunto de entidades.
  • Cree una nueva orden usung CreateObject().
  • Agregue el nuevo pedido al conjunto de entidades.

Cuando agrego una orden a la lista de pedidos del producto, que se bloquea tratando de fixup la asociación (ajuste de la propiedad de navegación producto en el nuevo orden)

CREATE TABLE [dbo].[Products](
    [productid] [int] IDENTITY(1,1) NOT NULL, 
    [productid2] [int] NOT NULL, 
    [productname] [nchar](10) NULL, 
CONSTRAINT [PK_Products] PRIMARY KEY CLUSTERED 
(
    [productid] ASC, 
    [productid2] 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].[Orders](
    [orderid] [int] NOT NULL, 
    [orderid2] [int] NOT NULL, 
    [ordername] [nchar](10) NULL, 
    [productid] [int] NULL, 
    [productid2] [int] NULL, 
CONSTRAINT [PK_orders] PRIMARY KEY CLUSTERED 
(
    [orderid] ASC, 
    [orderid2] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

Entity model

Código de estrellarse :

  var product = context.CreateObject<Products>(); 
      context.Products.AddObject(product); 
      var order = context.CreateObject<Orders>(); 
      context.Orders.AddObject(order); 

      product.Orders.Add(order); 
      if (order.Product != product) Console.WriteLine("error"); 

Excepción:

System.Data.EntityException was unhandled 
    Message=Unable to set field/property Product on entity type System.Data.Entity.DynamicProxies.Orders_A0290D8629F0336D278E5AEF2C0F2A91FF56726ED5E3A9FA668AC902696A8651. See InnerException for details. 
    Source=System.Data.Entity 
    StackTrace: 
     at System.Data.Objects.Internal.PocoPropertyAccessorStrategy.SetNavigationPropertyValue(RelatedEnd relatedEnd, Object value) 
     at System.Data.Objects.Internal.EntityWrapper`1.SetNavigationPropertyValue(RelatedEnd relatedEnd, Object value) 
     at System.Data.Objects.DataClasses.EntityReference`1.AddToObjectCache(IEntityWrapper wrappedEntity) 
     at System.Data.Objects.DataClasses.RelatedEnd.Add(IEntityWrapper wrappedTarget, Boolean applyConstraints, Boolean addRelationshipAsUnchanged, Boolean relationshipAlreadyExists, Boolean allowModifyingOtherEndOfRelationship, Boolean forceForeignKeyChanges) 
     at System.Data.Objects.DataClasses.RelatedEnd.Add(IEntityWrapper wrappedEntity, Boolean applyConstraints) 
     at System.Data.Objects.DataClasses.EntityCollection`1.Add(TEntity entity) 
     at Proxies.CSharp.Program.Main(String[] args) in Program.cs:line 20 
     at System.AppDomain._nExecuteAssembly(RuntimeAssembly assembly, String[] args) 
     at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args) 
     at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly() 
     at System.Threading.ThreadHelper.ThreadStart_Context(Object state) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx) 
     at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state) 
     at System.Threading.ThreadHelper.ThreadStart() 
    InnerException: System.NullReferenceException 
     Message=Object reference not set to an instance of an object. 
     Source=Proxies.CSharp 
     StackTrace: 
      at Proxies.CSharp.Orders.FixupProduct(Products previousValue, Boolean skipKeys) in Orders.cs:line 134 
      at Proxies.CSharp.Orders.set_Product(Products value) in Orders.cs:line 106 
      at System.Data.Entity.DynamicProxies.Orders_A0290D8629F0336D278E5AEF2C0F2A91FF56726ED5E3A9FA668AC902696A8651.SetBasePropertyValue(String , Object) 
      at lambda_method(Closure , Object , String , Object) 
      at System.Data.Objects.Internal.EntityProxyFactory.TrySetBasePropertyValue(Type proxyType, String propertyName, Object entity, Object value) 
      at System.Data.Objects.Internal.EntityProxyFactory.<>c__DisplayClass8.<CreateBaseSetter>b__7(Object entity, Object value) 
      at System.Data.Objects.Internal.PocoPropertyAccessorStrategy.SetNavigationPropertyValue(RelatedEnd relatedEnd, Object value) 

Nota: Funciona con entytobjects, funciona con entidades de auto-seguimiento, y funciona si la clave no es compuesta o no admite nulos.

¿Estoy haciendo algo mal o es un error real?

Respuesta

6

que tenía que corregir el TT Poco:

Chage las líneas (381,441 y 475):

<#=code.Escape(dependentProperty)#> = <#=code.Escape(navProperty)#>.<#=code.Escape(principalProperty)#>; 

por la línea:

<#=code.FieldName(dependentProperty)#> = <#=code.Escape(navProperty)#>.<#=code.Escape(principalProperty)#>; 
+0

Iba a decir que era mejor que informaras esto en el sitio del generador, luego verificaste y viste que ya lo hiciste. ¡Prestigio! – mcyalcin

0

Supongo que está utilizando this poco entity generotor, o haciendo una fijación de relación similar. Si es así, es un error Y usted está haciendo algo mal (es decir, hay formas de hacer lo que quiere sin golpear dicho error).

Si utiliza:

order.Product = product; 

en lugar de

product.Orders.Add(order); 

que iba a hacer lo que quiere.

El problema está en el método FixupProducts del objeto Order (o más bien en su interacción con productid setter). El método de reparación llama a productid setter, y el setter establece Product en null, y cuando el método Fixup pasa a establecer productid2, toma la excepción del puntero nulo al intentar usar ese Producto.

Por supuesto, puede abordar problemas similares en otros casos (aunque ahora no puedo pensar en ninguno). Estoy seguro de que puedes encontrar una solución adecuada si echas un vistazo a las clases generadas. En la parte superior de mi cabeza yo diría que saltear el setter en arreglos resolvería el problema, pero no he pensado en las implicaciones o probado esto, así que prueba bajo tu propio riesgo.

Probar sustituyendo:

productid = Product.productid; 

productid2 = Product.productid2; 

con

_productid = Product.productid; 

_productid2 = Product.productid2; 
+0

Gracias por su respuesta. Conocía esa solución, pero estaba buscando una solución que funcionara en ambos sentidos. Su segunda sugerencia parece funcionar, y no sé por qué no la probé en primer lugar;) Todas mis pruebas de unidad son verdes, así que supongo que es una buena corrección. – oleveau

Cuestiones relacionadas