Die Zuordnung des CLR-Typs zum EDM-Typ ist bei EF 6 & 5 nicht eindeutig.

75

Kann mir bitte jemand helfen, diesen Fehler zu beheben?

Das angegebene Schema ist ungültig. Fehler:

Die Zuordnung des CLR-Typs zum EDM-Typ ist nicht eindeutig, da mehrere CLR-Typen mit dem EDM-Typ 'City_DAL' übereinstimmen. Zuvor gefundener CLR-Typ 'CeossDAL.City_DAL', neu gefundener CLR-Typ 'CeossBLL.City_DAL'.

Das Hauptproblem, dass ich DAL habe und dies enthält die EF und BLL und dies enthält die gleichen Klassen der DAL, unterscheidet sich jedoch im Namespace und dies ist die Ursache des Problems

Ich kann nicht wissen, wie ich dieses Problem beseitigen kann. Können Sie mir bitte helfen?

Ich würde mich auch freuen, wenn mir jemand ein Beispiel für die Verwendung der n-Tier-Architektur mit EF geben würde

Vielen Dank

Mahmoud Samir
quelle

Antworten:

78

Verwenden Sie keine Klassen mit demselben nicht qualifizierten Namen. EF verwendet nur Klassennamen, um den in EDMX zugeordneten Typ zu identifizieren (Namespaces werden ignoriert). Es ist eine Konvention, Klassen von verschiedenen Namespaces einem einzelnen Modell zuzuordnen. Die Lösung für Ihr Problem besteht darin, Ihre Klassen in BLL anders zu benennen.

Ladislav Mrnka
quelle
Wenn ich die Klassen in BLL anders benenne, wie kann EF zwischen meiner Klasse in DAL und BLL abbilden?
Mahmoud Samir
1
EF wird nicht zwischen zwei Klassen zugeordnet. Es wird zwischen Entitäten im Diagramm zugeordnet und sucht nach einer einzelnen Klasse mit demselben Namen.
Ladislav Mrnka
3
Ich habe zwei Klassen, da ich mit einem Projekt mit 3 Ebenen arbeite (DAL / BLL / PL), also habe ich die EF in der DAL und ich habe die gleichen EF-Klassen in der BLL, in der BLL enthält jede Klasse Methoden, die verwendet wurden Um Methoden aus DAL und diese Methoden in der DAL aufzurufen, benötigen Sie beispielsweise ein Objekt aus der Klasse Product, das in der DAL vorhanden ist. Ich rufe diese Methoden jedoch aus der BLL auf. Wenn ich dieses Objekt an DAL-Methoden übergebe, erstelle ich aus dem Produkt ein Objekt, das existiert in der BLL und hier wird die Ausnahme ausgelöst.
Mahmoud Samir
4
@Ladislav Ich hätte EF ohne deine SO-Beiträge aufgegeben. Wieder gespeichert. Vielen Dank.
Neil Thompson
9
Eine EF-Kollision tritt nur auf, wenn zwei Klassen denselben Namen UND denselben Parametersatz haben.
Nikos Tsokos
41

Problemumgehung: Ändern Sie eine Eigenschaft für eine der beiden identischen Klassen.

EF stimmt mit Klassennamen UND Klasseneigenschaften überein. Also habe ich gerade einen Eigenschaftsnamen für eines der EF-Objekte geändert, und der Fehler ist verschwunden.

Als @Entrodus eine der anderen Antworten kommentierte:

Eine EF-Kollision tritt nur auf, wenn zwei Klassen denselben Namen UND denselben Parametersatz haben.

Matt
quelle
7
Für mein Geld ist dies die beste Antwort - ich würde lieber mit einem Eigenschaftsnamen als mit einem Klassennamen herumspielen
OutstandingBill
2
Ich habe sie nur in verschiedene Baugruppen gesteckt. Ich muss mich nicht damit anlegen
Erik Bergstedt
6
@ErikBergstedt Wenn Sie beide Assemblys in derselben Lösung verwenden, wird der Fehler angezeigt.
Tundey
4
In der widersprüchlichen Entität im EDMX habe ich versucht, den Namen einer der Eigenschaften zu ändern, eine weitere Eigenschaft hinzuzufügen und eine Teilklasse mit mehr "Dummy" -Eigenschaften hinzuzufügen ... Keine von beiden hat funktioniert. Nur das Ändern des Namens der Entität hat für mich funktioniert ...
Ymagine First
3
Das ist eine bedeutungslose Aussage. Klassen haben keine Parameter.
Suncat2000
11

Diese Frage zum MSDN-Forum könnte hilfreich sein. Es wird empfohlen, die BLL- und DAL-Klassen in separaten Assemblys zu platzieren.

Jarno
quelle
2
Wenn Sie beide Baugruppen in derselben Lösung verwenden, tritt der Fehler auf ... Ich habe genau das gleiche Problem. Beide sind unterschiedliche Datenbanken, haben aber die gleiche tblSetting. Ich habe es auf 2 verschiedene Baugruppen gelegt (immer auf verschiedene Baugruppen) und es funktioniert nicht :(
Sam
Ich habe beide Assemblys in derselben Lösung verwendet und der Fehler wurde nicht angezeigt, sodass ich nicht weiß, was mit diesem Kommentar los ist ...
Niklas
8

Für EF 6.x habe ich unter https://github.com/aspnet/EntityFramework/issues/941 einige Hinweise gefunden und dies in meiner Lösung durch Hinzufügen von Anmerkungen zum EDM-Typ behoben.

Ich habe die EDMX-Datei manuell bearbeitet und eine Zeile wie folgt geändert:

<EntityType Name="CartItem">

dazu:

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

oder verwenden Sie diese Option, wenn Sie einen anderen Typ an anderer Stelle haben:

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

Dabei ist EntityModel der für mein EF-Modell verwendete Namespace und MyApp der Namespace eines Geschäftsobjekts

Ekus
quelle
1
Dies funktionierte nicht für mich (versucht EF 6.0 und 6.3), arbeiten mit SQLite-Datenbank
Daniël Tulp
:-( Ich habe es nur mit MSSQL verwendet
Ekus
1
Dieser Github-Beitrag sagt auch, dass er hinzugefügt werden customannotation:UseClrTypessoll <EntityContainer>. (Arbeitete immer noch nicht für mich in EF 6)
Keith
1
Es funktioniert für mich mit MSSQL und EF 6.3.0 (habe keine anderen Kombinationen getestet).
Peter Ivan
6

In einigen Fällen ist dies eher ein Symptom als das eigentliche Problem. Für mich wird es normalerweise angezeigt, wenn ich versuche, eine Funktion in einer Linq-Abfrage aufzurufen, ohne zuvor .ToList () aufzurufen.

ZB wurde der Fehler, der mich hierher gebracht hat, verursacht, weil ich dies getan habe:

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

Ich musste .ToList () aufrufen, dann jedes Element durchlaufen und ihm den Typ zuweisen.

Kapitän Kenpachi
quelle
2
Vielen Dank! Dies war genau mein Problem, das in eine Aufzählung innerhalb der linq-Anweisung umgewandelt wurde.
Doug
1

Dies war möglicherweise nicht verfügbar, als die Frage gestellt wurde. Eine andere Lösung besteht darin, das EDMX zu löschen und es als Code-First-Entity-Datenmodell neu zu erstellen. In EF6 können Sie mit Code-First zwei Klassen mit demselben Namen aus verschiedenen Modell-Namespaces zuordnen, ohne einen Konflikt zu erzeugen.

Um das Entitätsdatenmodell in Visual Studio (2013) zu erstellen, gehen Sie zu "Hinzufügen"> "Neues Element ..."> "ADO.NET-Entitätsdatenmodell". Stellen Sie sicher, dass Sie die Option "Code First from Database" auswählen.

Tawab Wakil
quelle
Dies funktionierte nicht für mich (versucht EF 6.0 und 6.3), arbeiten mit SQLite-Datenbank
Daniël Tulp
Ich weiß nicht, ob es einen Unterschied macht, aber ich war auf MS SQL Server, als ich das tat.
Tawab Wakil
Das funktioniert absolut für mich. Ich habe eine Situation, in der keine der anderen Lösungen zuzutreffen scheint.
Dave
Dies liegt daran, dass die Entitätstypen für Code First unterschiedlich mit Anmerkungen versehen sind. Siehe @ Ekus 'Antwort unter stackoverflow.com/a/44931349/1307074 .
Suncat2000
1

Ich habe den obigen Fehler erhalten, weil ich für beide Verbindungszeichenfolgen den gleichen Wert für Metadaten hatte, der in der Konfigurationsdatei meines Hauptprojekts angegeben ist, wie unten:

<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" />

Am Ende habe ich die richtige Verbindungszeichenfolge aus der Konfigurationsdatei des EntitiesB-Projekts kopiert.

Kristianne Nerona
quelle
Ich denke, das OP hat das Problem mit dem Namen Entitätsname. Ich habe es auch getan ... Ich habe die richtige Verbindungszeichenfolge in meine Web.config eingefügt. Es funktioniert immer noch nicht :(
Sam
Das Problem wurde behoben, nachdem Sie Ihre Antwort gesehen und 3 Stunden lang herausgefunden hatten.
ChupChapCharli
0

Ein weiterer Grund für diesen Fehler: Wenn Sie benutzerdefinierte Assemblys mit Assembly.LoadFile laden, die über Edmx-Dateien verfügen, die bereits in den Speicher geladen wurden. Dadurch werden doppelte Klassen erstellt, die dem Entity Framework nicht gefallen.

Thomas
quelle
0

Für mich lag dies daran, dass ich versucht habe, auf einen Typ mit demselben Namen in der falschen Kontextinstanz zuzugreifen.

Sag beides ContextAund ContextBhabe SomeType. Ich habe versucht, ContextA.SomeTypeauf eine Instanz von zuzugreifen ContextB.

Dave Cousineau
quelle
0

Fügen Sie das EntityFramework einfach als "Code First from Database" und nicht als "EF Designer from Database" hinzu. Dies hat mein Problem gelöst, hat aber eine Schattenseite. Wenn Sie Ihre Datenbank ändern, müssen Sie alle Klassen entfernen und erneut hinzufügen oder nur die Klassen bearbeiten. Ich verwende die letzte, wenn ich die Eigenschaften der Spalten ändere, z. B. "Zulassen" null "oder die Größe einer Zeichenfolge. Wenn Sie jedoch Spalten hinzufügen, empfehle ich, die Klassen zu entfernen und erneut hinzuzufügen.

Felipe Batista Suardi
quelle
0

Ich konnte dieses Problem lösen, ohne die Klassen, Eigenschaften oder Metadaten umzubenennen.

Ich hatte mein Projekt mit einer T4-Transformation eingerichtet, die Entitätsobjekte in einem DAL-Projekt erstellt, und einer T4-Transformation, die Domänenobjekte in einem Domänenprojekt erstellt. Beide verweisen auf EDMX, um identische Objekte zu generieren, und ordneten dann die DAL-Objekte den Domänenobjekten zu .

Der Fehler trat nur auf, wenn ich in meinen Abfragen auf andere Klassen (in meinem Fall Aufzählungen) aus der Domänenassembly verwies. Als ich sie entfernte, verschwand der Fehler. Es sieht so aus, als hätte EF aus diesem Grund meine Domain-Assembly geladen, die anderen gleichnamigen Klassen gesehen und in die Luft gesprengt.

Um dies zu beheben, habe ich eine separate Assembly erstellt, die nur meine T4-transformierten Domänenklassen enthielt. Da ich diese nie in einer Abfrage verwenden muss (erst nach der Abfrage, der sie zugeordnet werden soll), tritt dieses Problem nicht mehr auf. Dies scheint sauberer und einfacher als die folgenden Antworten.

Carson
quelle
0

Wenn Sie 2 Verbindungszeichenfolgen in der Webkonfiguration haben, aber eine Verbindungszeichenfolge verwenden möchten, verwenden Sie die dynamische Verbindungszeichenfolge zum Erstellen anderer Entitäten. Ich habe edmx (db first) und code first Entities in meiner Lösung. Ich verwende diese Klasse in Code First Entities.

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;
        }
    }
}

Und wenn ich Entitäten anrufe

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

    return _context;

}
set { _context = value; }
}
Cetin Sahin
quelle
0

Ich denke, Sie haben eine Klasse X mit dem Namen "MyClass" in Entitätsmodellen und eine andere Klasse mit dem Namen "MyClass" in demselben WorkFolder oder Extended der ersten Klasse. Das ist mein Problem und ich behebe es.

Maximiliano Cesán
quelle
-9

Es gibt eine Bibliothek namens AutoMapper, die Sie herunterladen können. Es hilft Ihnen, Klassenzuordnungen von einem Typ zum anderen zu definieren.

Mapper.CreateMap<Model.FileHistoryEFModel, DataTypes.FileHistory>();
Mapper.CreateMap<DataTypes.FileHistory, Model.FileHistoryEFModel>();
pkamathk
quelle
12
nicht wirklich anwendbar auf die Benutzerfrage. Die Verwendung von Automapper wird nicht nur sein Problem beheben.
Calvin