Зіставлення типу CLR із типом EDM неоднозначне з EF 6 & 5?


75

Будь-ласка, будь-хто може допомогти мені виправити цю помилку?

Вказана схема недійсна. Помилки:

Зіставлення типу CLR із типом EDM неоднозначне, оскільки кілька типів CLR відповідають типу EDM 'City_DAL'. Раніше знайдений тип CLR 'CeossDAL.City_DAL', нещодавно знайдений тип CLR 'CeossBLL.City_DAL'.

Основна проблема, що у мене є DAL, і вона містить EF і BLL, і вона містить ті самі класи DAL, але відрізняється простором імен, і саме це спричиняє проблему

Я не можу знати, як позбутися цієї проблеми, можете, будь ласка, допомогти мені?

Також я буду вдячний, якщо хтось дасть мені зразок для використання n-рівня архітектури з EF

Дякую

Відповіді:


78

Не використовуйте класи з однаковим некваліфікованим іменем - EF використовує лише імена класів для ідентифікації типу, зіставленого в EDMX (простори імен ігноруються) - це дозвіл, що дозволяє зіставляти класи з різних просторів імен в одну модель. Рішення вашої проблеми полягає в тому, щоб інакше називати свої класи в BLL.


Якщо я називаю класи в BLL інакше, як EF може зіставити між моїми класами в DAL і BLL?
Махмуд Самір

1
EF не співпадає між двома класами. Він співпадає між сутностями на діаграмі та шукає один клас з однаковим ім’ям.
Ladislav Mrnka

3
У мене є два класи, оскільки я працюю з проектом із трирівневим (DAL / BLL / PL), тому у мене є EF в DAL і у мене однакові EF-класи в BLL, у BLL кожен клас містить методи, які використовувались для виклику методів з DAL і цих методів у DAL потрібен такий об'єкт із класу Product, який існує в DAL, але я викликаю ці методи з BLL, тому, коли я передаю цей об'єкт методам DAL, я створюю об'єкт з Product, який існує в BLL, і тут висувається виняток.
Махмуд Самір

4
@Ladislav Я б відмовився від EF без твоїх публікацій SO. Знову збережено. Дякую.
Ніл Томпсон,

9
Зіткнення EF відбувається лише тоді, коли два класи мають однакову назву І однаковий набір параметрів.
Нікос Цокос

42

Вирішення проблеми: Змініть властивість одного з двох однакових класів.

EF відповідає імені класу І властивостям класу. Тож я просто змінив назву властивості на одному з об’єктів EF, і помилка зникла.

Як @Entrodus прокоментував одну з інших відповідей:

Зіткнення EF відбувається лише тоді, коли два класи мають однакову назву І однаковий набір параметрів.


7
За мої гроші це найкраща відповідь - я волів би возитися з назвою власності, ніж з назвою класу
OutstandingBill

2
Я просто
складав

6
@ErikBergstedt Якщо ви використовуєте обидві збірки в одному рішенні, ви почнете отримувати помилку.
Тенді,

4
У суперечливій сутності в EDMX я спробував змінити назву одного із властивостей, додавши іншу властивість, додавши клас Частковий з більше "фіктивними" властивостями ... Жоден з них не працював. У мене спрацювала лише зміна назви
Сутності

3
Це безглузде твердження. Класи не мають параметрів.
Suncat2000

11

Це запитання форуму MSDN може бути корисним. Пропонується розміщувати класи BLL та DAL в окремих збірках.


2
Якщо ви використовуєте обидві збірки в одному і тому ж рішенні, помилка виникне ... У мене точно така ж проблема. Обидві різні бази даних, але мають однакову tblSetting. Я ставлю його на 2 різні збірки (завжди надягаю різні збірки), і це не працює :(
Сем,

я використовував обидва збірки в одному рішенні, і помилка не з'являлася, тому я не знаю, що відбувається з цим коментарем ...
Ніклас,

8

Для EF 6.x я знайшов деякі примітки за адресою https://github.com/aspnet/EntityFramework/issues/941 і виправив це у своєму рішенні, додавши анотацію до типу EDM.

Я відредагував файл EDMX вручну і змінив такий рядок:

<EntityType Name="CartItem">

до цього:

<EntityType Name="CartItem" customannotation:ClrType="EntityModel.CartItem">

або використовуйте це, якщо у вас є інший тип в іншому місці:

<EntityType Name="CartItem" customannotation:ClrType="MyApp.CartItem, MyApp, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null">

де EntityModel - це простір імен, що використовується для моєї моделі EF, а MyApp - простір імен бізнес-об'єкта


1
Це не спрацювало для мене (спробував EF 6.0 та 6.3), робота з базою даних SQLite
Даніель Тулп

:-( Я використовував його лише з MSSQL
Екус

1
Це Github пост також говорить , щоб додати customannotation:UseClrTypesдо <EntityContainer>. (Досі не працював для мене в EF 6)
Кіт,

1
Це працює для мене з MSSQL та EF 6.3.0 (не перевіряв інші комбінації).
Петро Іван,

6

У деяких випадках це більше симптом, ніж реальна проблема. Для мене це зазвичай з’являється, коли я намагаюся викликати функцію всередині запиту Linq, не спочатку викликаючи .ToList ().

Наприклад, помилка, яка привела мене сюди, спричинена тим, що я зробив це:

var vehicles = DB.Vehicles.Select(x => new QuickSearchResult()
{
    BodyText = x.Make + " " + x.Model + "<br/>"
    + "VIN: " + x.VIN + "<br/>"
    + "Reg: " + x.RegistrationNumber +"<br/>"
    + x.AdditionalInfo
    type = QuickSearchResultType.Vehicle,//HERE. Can't use an enum in an IQueryable.
    UniqueId = x.VehicleID
});

Мені довелося зателефонувати .ToList (), потім перебирати кожен елемент і призначати йому тип.


2
Дякую! Це було саме моє питання, прив’язка до переліку в операторі linq.
Даг,

1

Можливо, це було недоступно, коли було задано запитання, але іншим рішенням є видалення EDMX та відтворення його як моделі даних сутності, котра першою використовує код. У EF6, з використанням коду, ви можете зіставити два класи з однаковим іменем із різних просторів імен моделі, не створюючи конфлікту.

Щоб створити модель даних сутності у Visual Studio (2013), перейдіть до пункту «Додати»> «Новий елемент ...»> «Модель даних сутності ADO.NET». Не забудьте вибрати параметр "Перший код із бази даних".


У мене це не спрацювало (спробував EF 6.0 та 6.3), робота з базою даних SQLite
Даніель Тулп

Я не знаю, чи це має значення, але коли я це робив, я працював на MS SQL Server.
Tawab Wakil

Це абсолютно працює для мене. У мене ситуація, коли, здається, не застосовується жодне з інших рішень.
Дейв,

Це пов’язано з тим, що типи об’єктів кодуються по-різному для Code First. Див @ відповідь Ekus за адресою stackoverflow.com/a/44931349/1307074 .
Suncat2000

1

Я отримав помилку вище, оскільки для обох рядків підключення у мене було однакове значення для метаданих, вказаних у конфігураційному файлі мого основного проекту, як показано нижче:

<add name="EntitiesA" connectionString="metadata=res://*/EntitiesA.csdl|res://*/EntitiesA.ssdl|res://*/EntitiesA.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=localhost;initial catalog=MyDatabase;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />

<add name="EntitiesB" connectionString="metadata=res://*/EntitiesA.csdl|res://*/EntitiesA.ssdl|res://*/EntitiesA.msl;provider=System.Data.SqlClient;provider connection string=&quot;data source=localhost;initial catalog=MyDatabase;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework&quot;" providerName="System.Data.EntityClient" />

У підсумку я скопіював правильний рядок підключення з конфігураційного файлу проекту EntitiesB.


Я думаю, що OP має проблеми з іменем сутності імені. Я теж ... Я правильно вказав рядок підключення у своєму Web.config. Це все ще не працює :(
Сем,

Виправлено проблему, побачивши вашу відповідь і витративши 3 години на з’ясування.
ChupChapCharli

0

Ще одна причина, через яку ви можете отримати цю помилку: якщо ви завантажуєте власні збірки за допомогою Assembly.LoadFile, які містять файли edmx, які вже завантажені в пам’ять. Це створює повторювані класи, які структурі сутності не подобаються.


0

Для мене це було тому, що я намагався отримати доступ до типу з тим самим іменем на неправильному екземплярі контексту.

Скажу так ContextAі ContextBє SomeType. Я намагався отримати доступ ContextA.SomeTypeдо екземпляра ContextB.


0

Просто додайте EntityFramework як "Код спочатку з бази даних", а не як "EF Designer з бази даних". Це вирішило мою проблему, але вона має темну сторону. Якщо ви зміните базу даних, вам доведеться видалити всі класи та додати її знову, або просто відредагувати класи, я використовую останнє, коли змінюю властивості стовпців, наприклад "Дозволяє null "або розмір рядка. Але якщо ви додасте стовпці, я рекомендую видалити і знову додати класи.


0

Я зміг вирішити цю проблему, не перейменовуючи класи, властивості або метадані.

У мене було налаштування проекту за допомогою трансформації T4, що створює об’єкти сутності в проекті DAL, і трансформації T4, що створює об’єкти домену в проекті домену, обидва посилаючись на EDMX для створення ідентичних об’єктів, а потім я зіставляв об’єкти DAL з об’єктами домену .

Помилка сталася лише тоді, коли я посилався на інші класи (переліки в моєму випадку) із збірки Domain у своїх запитах. Коли я їх видалив, помилка зникла. Схоже на те, що EF завантажував мою збірку домену через це, бачачи інші ідентичні класи та підриваючи.

Щоб вирішити цю проблему, я зробив окрему збірку, яка містила лише мої трансформовані доменні класи T4. Оскільки мені ніколи не потрібно використовувати їх всередині запиту (лише після запиту, до якого потрібно зіставити), у мене більше немає цієї проблеми. Це здається чистішим та простішим, ніж відповіді нижче.


0

якщо у вас є 2 рядки підключення у веб-конфігурації, але ви хочете використовувати один рядок підключення, ви використовуєте динамічне створення рядка підключення інших об'єктів. У моєму рішенні є edmx (db first) і code first Entities. Я використовую цей клас у сутності First.

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data.Entity.Core.EntityClient;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Data
{
    public class SingleConnection
    {
        private SingleConnection() { }
        private static SingleConnection _ConsString = null;
        private String _String = null;

        public static string ConString
        {
            get
            {
                if (_ConsString == null)
                {
                    _ConsString = new SingleConnection { _String = SingleConnection.Connect() };
                    return _ConsString._String;
                }
                else
                    return _ConsString._String;
            }
        }

        public static string Connect()
        {
            string conString = ConfigurationManager.ConnectionStrings["YourConnectionStringsName"].ConnectionString;

            if (conString.ToLower().StartsWith("metadata="))
            {
                System.Data.Entity.Core.EntityClient.EntityConnectionStringBuilder efBuilder = new System.Data.Entity.Core.EntityClient.EntityConnectionStringBuilder(conString);
                conString = efBuilder.ProviderConnectionString;
            }

            SqlConnectionStringBuilder cns = new SqlConnectionStringBuilder(conString);
            string dataSource = cns.DataSource;
            SqlConnectionStringBuilder sqlString = new SqlConnectionStringBuilder()
            {
                DataSource = cns.DataSource, // Server name
                InitialCatalog = cns.InitialCatalog,  //Database
                UserID = cns.UserID,         //Username
                Password = cns.Password,  //Password,
                MultipleActiveResultSets = true,
                ApplicationName = "EntityFramework",

            };
            //Build an Entity Framework connection string
            EntityConnectionStringBuilder entityString = new EntityConnectionStringBuilder()
            {
                Provider = "System.Data.SqlClient",
                Metadata = "res://*",
                ProviderConnectionString = sqlString.ToString()
            };
            return entityString.ConnectionString;
        }
    }
}

І коли я називаю сутності

private static DBEntities context
{
get
{
    if (_context == null)
        _context = new DBEntities(SingleConnection.ConString);

    return _context;

}
set { _context = value; }
}

0

Я думаю, у вас є клас X із назвою "MyClass" у моделях сутності та інший клас, який називається "MyClass" у тій самій WorkFolder або Extended першого класу. Це моя проблема, і я її виправляю.


-9

Існує бібліотека під назвою AutoMapper, яку ви можете завантажити. Це допоможе вам визначити зіставлення класів від одного типу до іншого.

Mapper.CreateMap<Model.FileHistoryEFModel, DataTypes.FileHistory>();
Mapper.CreateMap<DataTypes.FileHistory, Model.FileHistoryEFModel>();

12
насправді не застосовується до запитань користувачів. Використання automapper не просто вирішить його проблему.
Кальвін
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.