Исключение при исправлении ассоциации с обнуляемыми составными внешними ключами - PullRequest
6 голосов
/ 16 февраля 2011

У меня проблема с Pocos и обнуляемыми внешними ключами. У меня есть 2 таблицы (заказы и продукты), каждая таблица имеет составной первичный ключ (orderid, orderid2) и (productid, productid2) И я установил связь 0,1 .. * между двумя таблицами. Один заказ может быть связан с 0 или 1 товаром. И у одного продукта есть * заказы, связанные с ним.

Как вылететь:

  • Создайте новый продукт с помощью CreateObject ().
  • Добавьте новый продукт к тогда entityset.
  • Создание нового заказа с помощью CreateObject ().
  • Добавить новый Заказ в набор сущностей.

Когда я добавляю заказ в список заказов продукта, происходит сбой при попытке исправить связь (установка свойства навигации продукта для нового заказа)

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

Код сбоя:

            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");

Исключение:

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)

Примечание: он работает с объектами-энтитобъектами, работает с объектами с самопроверкой и работает, если ключ не является составным или не обнуляемым.

Я что-то не так делаю или это реальная ошибка?

Ответы [ 2 ]

6 голосов
/ 25 февраля 2011

Мне пришлось исправить poco TT:

Измените строки (381, 441 и 475):

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

по строке:

<#=code.FieldName(dependentProperty)#> = <#=code.Escape(navProperty)#>.<#=code.Escape(principalProperty)#>;
0 голосов
/ 24 февраля 2011

Я предполагаю, что вы используете этот генотип сущности poco или выполняете аналогичную фиксацию отношений.Если это так, это ошибка, и вы делаете что-то не так (то есть есть способы сделать то, что вы хотите, не затрагивая указанную ошибку).

Если вы используете:

order.Product = product;

вместоиз

product.Orders.Add(order);

это будет делать то, что вы хотите.

Проблема в методе FixupProducts объекта Order (или, скорее, в его взаимодействии с установщиком productid).Метод Fixup вызывает программу установки productid, и метод установки устанавливает для Product значение null, а когда метод Fixup продолжает устанавливать продукцию productid2, он принимает исключение нулевого указателя при попытке использовать этот продукт.

Конечно, вы можете столкнуться с похожими проблемами.в других случаях (хотя я не могу думать ни о каком прямо сейчас).Я уверен, что вы можете найти правильное решение, если вы посмотрите на сгенерированные классы.Вдобавок ко всему, я сказал бы, что пропуск сеттера в исправлениях решит проблему, но я не думал о последствиях и не проверял это, поэтому попробуйте на свой страх и риск.

Попробуйте заменить:

productid = Product.productid;

productid2 = Product.productid2;

на

_productid = Product.productid;

_productid2 = Product.productid2;
...