Entity Framework 6.0 Code first - получаване на дублирани елементи в проста заявка при филтриране по първичен ключ

В моя проект използваме EF Code First (v.6.0.0.0) и MS SQL Server 2012.

Актуализирах до Entity Framework до 6-та версия. Странното е, че в някакъв момент след актуализацията започнах да получавам дублирани елементи, докато филтрирах записи по първичния ключ.

Първо започнах да получавам изключение „Поредица съдържа повече от един елемент“ в следния код

var cateringService = context.CateringServices
                             .SingleOrDefault(x => x.Id == query.CateringServiceId)

Проверих базата данни и параметъра - Id е първичен ключ, маркиран е като уникален и параметърът беше валиден. Тъй като Id беше зададен като първичен ключ в картографирането:

this.HasKey(x => x.Id);

Замених обаждането с FirstOrDefault и кодът работи добре. Опитах се да извлека всички елементи, които изравняват предиката, използвайки следния код:

var cateringServices = context.CateringServices
                              .Where(x => x.Id == query.CateringServiceId)
                              .ToList();

Изглежда, че получавам 13 екземпляра на обекта „CateringService“, препращащ към един и същ ред. Моля, вижте приложените екранни снимки:

въведете описание на изображението туквъведете описание на изображението тук

Освен това започнах да получавам изключение A relationship multiplicity constraint violation occurred: An EntityReference can have no more than one related object, but the query returned more than one related object. при достъп до обектите CateringService чрез препратка към обект. Използваме мързеливия подход и мързеливото зареждане е активирано.

Когато се опитвате да получите достъп до „CateringService“ с помощта на Include("CateringService") всичко работи добре, но не можем просто да заменим всички SingleOrDefault повиквания и да премахнем всички употреби на мързеливо зареждане от проекта в този момент.

Моля за съвет.

АКТУАЛИЗАЦИЯ

Съжалявам, че не съм съвсем ясен. В базата данни има един запис, който отговаря на условието. Колоната Id е зададена като първичен ключ, така че е уникална.

АКТУАЛИЗАЦИЯ 2

По-долу е кодът от миграцията, генерирана от EF въз основа на плавни съпоставяния.

CreateTable(
            "dbo.CateringServices",
            c => new
                {
                    Id = c.Int(nullable: false, identity: true),
                    Name = c.String(nullable: false, maxLength: 200),
                    CreatedDate = c.DateTime(nullable: false),
                    CultureString = c.String(maxLength: 10),
                    AddressId = c.Int(),
                    CateringServiceGroupId = c.Int(),
                    ContactInformationId = c.Int(),
                })
            .PrimaryKey(t => t.Id)
            .ForeignKey("dbo.Addresses", t => t.AddressId, cascadeDelete: true)
            .ForeignKey("dbo.CateringServiceGroups", t => t.CateringServiceGroupId)
            .ForeignKey("dbo.ContactInformation", t => t.ContactInformationId, cascadeDelete: true)
            .Index(t => t.AddressId)
            .Index(t => t.CateringServiceGroupId)
            .Index(t => t.ContactInformationId);

person danyloid    schedule 12.12.2013    source източник
comment
Каква е дефиницията на query във вашия код? (x.Id == query.CateringServiceId)   -  person Richard Deeming    schedule 16.12.2013
comment
Това е екземпляр на наистина прост клас - имащ само едно свойство public Int32 CateringServiceId { get; set; }   -  person danyloid    schedule 16.12.2013
comment
но се опитах да използвам твърдо кодираната стойност, напр. x => x.Id == 1. или всеки друг съществуващ идентификатор в базата данни. все още получава същия резултат.   -  person danyloid    schedule 16.12.2013
comment
Проверихте ли свързаните таблици (Addresses, CateringServiceGroups и ContactInformation), за да видите дали съдържат дублиращи се записи?   -  person Richard Deeming    schedule 16.12.2013
comment
да, не го правят, но изглежда, че проблемът е бил в друго съпоставяне на обект в следните редове: this.HasOptional(x => x.CateringService).WithOptionalDependent().Map(x => x.MapKey("CateringServiceId"));. по някаква причина при заявка към таблицата CateringServices имаше ляво външно свързване.   -  person danyloid    schedule 16.12.2013
comment
Бихте ли могли да проверите SQL заявката, генерирана от Entity Framework и може би ще има ключ към това какво не е наред? Въз основа на вашето описание мисля, че има повече от една връзка между CateringServices и други обекти и това причинява дубликати.   -  person Aleksei Poliakov    schedule 21.12.2013


Отговори (2)


Трябва да използвате FirstOrDefault вместо SingleOrDefault. тъй като вашият кратък екран има същата стойност за Id cloumn. Така че трябва да искате това.

в противен случай трябва да проверите, че ID е първичен ключ. и зададете отметка за самоличност да за вашата колона с идентификатор

защото

FirstOrDefault()

е за случаите, когато се очаква да присъстват нула или повече резултати във входната колекция и извикването връща първия елемент, ако има множество резултати, По подразбиране, ако няма.

SingleOrDefault()

е за случаите, когато се очаква нула или един резултат във входната колекция и извикването връща един резултат, ако има точно един резултат, по подразбиране ако няма резултати и изключение, ако има повече от един резултат.

и вижте това LINQ: Кога да използвате SingleOrDefault срещу FirstOrDefault () с критерии за филтриране

Актуализирано:

Тъй като сте направили обратно проектиране на базата данни, когато колоната Id все още не е зададена като IDENTITY, първият модел на кода е генериран с DatabaseGeneratedOption.None, зададено за свойството Id на обекта.

Това кара EF да създаде оператор за вмъкване с набора Id, който вече не работи след промяна на колоната на IDENTITY.

Трябва ръчно да поправите тази конфигурация, като я зададете на DatabaseGeneratedOption.Identity или просто я премахнете напълно, тъй като това е стойността по подразбиране за целочислени полета.

Трябва да се промениш

this.HasKey(e => e.Id);
   Property(e => e.Id).HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);

Още подробности

EF Code First 5.0.rc Migrations не актуализирайте свойството за самоличност

Entity Framework 5 code-first не създава база данни

Редактиране: Моля, изтрийте старите си стойности на таблицата и я генерирайте отново или премахнете същите първични ключови редове. Трябва да се наложи да генерирате отново своите CateringServices стойности на таблицата :), ако проблемите все още не са изчистени.

person Ramesh Rajendran    schedule 12.12.2013
comment
вярно Но ако сте прочели заглавието на въпроса, може да сте забелязали, че това не е съвсем така, когато FirstOrDefault е трябвало да се използва. Но проблемът е, че трябва да има един единствен запис. Както е в базата данни. И така или иначе вашият отговор не решава проблема с грешката „Възникна нарушение на ограничението за множественост на връзката“. - person danyloid; 12.12.2013
comment
Да, но вашият кратък екран има същата стойност за Id cloum. Така че трябва да искате това - person Ramesh Rajendran; 12.12.2013
comment
вярно За това питам. Заявих, че идентификаторът е уникален в базата данни. - person danyloid; 12.12.2013
comment
Проверих базата данни и параметъра - Id е първичен ключ, уникален е и параметърът беше валиден. - person danyloid; 12.12.2013
comment
прочетете още веднъж в отговора ми. задали ли сте IsIdentity=true във вашата колона Id? - person Ramesh Rajendran; 12.12.2013
comment
Можете ли да покажете настройката на първичния ключ? и Настройки за идентичност? - person Ramesh Rajendran; 12.12.2013
comment
Направих. Използвам EF Code First и Fluent Mappings. Това е кодът, отговорен за това - this.HasKey(x =› x.Id); - person danyloid; 12.12.2013
comment
Мисля, че isidentity не е зададена, така че имате проблема. Моля, уверете се, че is identity е зададена:google.co.in/ - person Ramesh Rajendran; 12.12.2013
comment
Може да добавя и плавното картографиране, но това ще направи въпроса твърде труден за четене. - person danyloid; 12.12.2013
comment

Кое устройство използвате за отстраняване на грешки? Само CPU на Intel е разрешен за отстраняване на грешки с SDK на Intel. intel graphics няма да работи.

Проверете следното: Използвате ли компилатора на intel вместо компилатора MSVC? щракнете с десния бутон върху проекта -> конвертирайте в проект opencl / използвайте компилатор на intel c++

Настройки на компилатора: меню Code_builder -> opencl debugger -> опции

отметнете "разрешаване на отстраняване на грешки в ядрото на opencl" посочете работен елемент, който искате да отстраните (0,0,0 е добре и първата нишка, ако използвате само глобален размер на workgrp и не локален)

раздел api дебъгер: отметнете активиране на opencl api дебъгер

след -g -s трябва да добавите пътя към ядрото като:

options = " -g -s E:\\prog\\clproj\\Clproj\\kernel.cl";

Предадохте ли опциите char* на clBuildProgram по този начин?

clBuildProgram(program, 0, NULL, options, NULL, NULL);

Уверете се, че използвате intel opencl libs, а не други opencl libs.

За правилна настройка с Vstudio вижте тук:

ръководство за Intel

- person Ramesh Rajendran; 12.12.2013
comment
Актуализирах решението, моля, разгледайте го сега :) - person Ramesh Rajendran; 12.12.2013
comment
Не сме извършили обратно инженерство на базата данни. Проектът използва EF Code First от самото начало. Започнахме да изпитваме проблема точно след актуализацията до 6-та версия. Вашето решение обаче проработи)) - person danyloid; 12.12.2013
comment
съжалявам за демаркирането на въпроса и благодаря за усилията. обаче проектът се появи отново. изглежда има друга причина за това. - person danyloid; 16.12.2013
comment
@danyloid - Мисля, че вашата база данни има стари стойности със същата стойност на първичния ключ, така че сте получили грешката, изчистете таблицата и още един опит - person Ramesh Rajendran; 17.12.2013

Можете да използвате .Top(1) вместо .FirstOrDefault() или .SingleOrDefault().

Аз съм нов за Linq, но както знам top() ще върне само определен брой редове. Не знам за FirstOrDefault и SingleOrDefault.

person Anand    schedule 16.12.2013
comment
Всъщност трябва да използвате FirstOrDefault, в противен случай top(1) все още връща IEnumberable. FirstOrDefault() ще върне първия елемент в последователността, ако има някакви или ще върне null SingleOrDefault ще върне null, ако няма такъв, елемента, ако има един (и само един) и ще хвърли изключение ако има няколко елемента - person finman; 23.12.2013