web-dev-qa-db-fra.com

Le mappage du type CLR sur le type EDM est ambigu avec EF 6 & 5?

S'il vous plaît, tout le monde peut m'aider à corriger cette erreur?

Le schéma spécifié n'est pas valide. Les erreurs: 

Le mappage du type CLR sur le type EDM est ambigu, car plusieurs types de CLR correspondent au type EDM 'City_DAL'. Type CLR précédemment trouvé 'CeossDAL.City_DAL', type CLR nouvellement trouvé 'CeossBLL.City_DAL'.

Le problème principal que j'ai DAL et cela contient les EF et BLL et cela contient les mêmes classes du DAL mais diffère dans l'espace de noms et c'est ce qui cause le problème

Je ne sais pas comment me débarrasser de ce problème, pouvez-vous m'aider s'il vous plaît?

J'apprécierais aussi si quelqu'un me donnait un exemple d'utilisation de l'architecture n-tier avec EF

Je vous remercie 

62
Mahmoud Samir

N'utilisez pas de classes avec le même unqualified name - EF utilise uniquement des noms de classe pour identifier le type mappé dans EDMX (les espaces de nom sont ignorés). Il s'agit d'une convention permettant d'autoriser le mappage de classes de différents espaces de nom sur un seul modèle. La solution à votre problème consiste à nommer vos classes dans BLL différemment.

73
Ladislav Mrnka

Solution: modifiez une propriété sur l'une des deux classes identiques.

EF correspond au nom de la classe ET aux propriétés de la classe. Je viens donc de changer un nom de propriété sur l'un des objets EF, et l'erreur a disparu.

Comme @Entrodus a commenté l'une des autres réponses:

La collision EF ne se produit que lorsque deux classes ont le même nom ET le même ensemble de paramètres.

37
Matt

Cette question sur le forum MSDN pourrait être utile. Il suggère de placer les classes BLL et DAL dans des assemblys séparés.

10
Jarno

Pour EF 6.x, j'ai trouvé des notes sur https://github.com/aspnet/EntityFramework/issues/941 et j'ai résolu ce problème dans ma solution en ajoutant une annotation au type EDM.

J'ai édité le fichier EDMX manuellement et modifié une ligne comme ceci:

<EntityType Name="CartItem">

pour ça:

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

ou utilisez ceci si vous avez un type existant ailleurs:

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

EntityModel est l'espace de nom utilisé pour mon modèle EF et MyApp est l'espace de nom d'un objet métier

5
Ekus

Dans certains cas, il s'agit davantage d'un symptôme que du problème réel. Pour moi, il apparaît généralement lorsque j'essaie d'appeler une fonction dans une requête Linq sans appeler .ToList () auparavant.

Par exemple. l'erreur qui m'a amené ici a été causée parce que j'ai fait ceci:

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

J'ai dû appeler .ToList (), puis parcourir chaque élément et lui attribuer le type.

4
Captain Kenpachi

Cela n'était peut-être pas disponible lorsque la question a été posée, mais une autre solution consiste à supprimer l'EDMX et à le recréer en tant que modèle de données d'entité premier code. Dans EF6, avec le code d'abord, vous pouvez mapper deux classes portant le même nom à partir d'espaces de nom de modèle différents sans créer de conflit.

Pour créer le modèle de données d'entité dans Visual Studio (2013), accédez à "Ajouter"> "Nouvel élément ..."> "Modèle de données d'entité ADO.NET". Assurez-vous de choisir l'option "Code d'abord de la base de données".

1
Tawab Wakil

Je pense que vous avez une classe X nommée "MyClass" dans Entity Models et une autre classe appelée "MyClass" dans le même dossier de travail ou étendu de la première classe . C'est mon problème et je le répare.

0
Maximiliano Cesán

J'ai pu résoudre ce problème sans renommer les classes, propriétés ou métadonnées.

J'avais configuré mon projet avec une transformation T4 créant des objets d'entité dans un projet DAL et une transformation T4 créant des objets de domaine dans un projet de domaine, faisant tous deux référence à EDMX pour générer des objets identiques, puis je mappais les objets DAL aux objets de domaine. .

L'erreur s'est produite uniquement lorsque je faisais référence à d'autres classes (énumérations dans mon cas) de l'assembly de domaine dans mes requêtes. Quand je les ai enlevés, l'erreur est partie. Il semblerait que EF chargeait mon Domain Domain à cause de cela, voyant les autres classes portant le même nom et explosant.

Pour résoudre ce problème, j'ai créé un assembly séparé contenant uniquement les classes de domaine transformées T4. Comme je n'ai jamais besoin de les utiliser dans une requête (uniquement après la requête à mapper), je n'ai plus ce problème. Cela semble plus propre et plus facile que les réponses ci-dessous.

0
Carson

J'ai eu l'erreur ci-dessus car pour les deux chaînes de connexion, j'avais la même valeur pour les métadonnées spécifiées dans le fichier de configuration de mon projet principal, comme ci-dessous:

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

J'ai fini par copier la chaîne de connexion correcte à partir du fichier de configuration du projet EntitiesB.

0
Kristianne Nerona

Pour moi, c'était parce que j'essayais d'accéder à un type portant le même nom sur la mauvaise instance de contexte.

Dites que ContextA et ContextB ont SomeType. J'essayais d'accéder à ContextA.SomeType sur une instance de ContextB.

0
Dave Cousineau

si vous avez deux chaînes de connexion dans Web Config mais que vous souhaitez utiliser une chaîne de connexion Vous utilisez une chaîne de connexion dynamique pour créer d'autres entités. J'utilise cette classe dans les premières entités de code.

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

Et quand j'appelle des entités 

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

    return _context;

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

Ajoutez simplement EntityFramework en tant que "Code premier de la base de données" et non en tant que "Concepteur EF de la base de données". Cela a résolu mon problème, mais il a un côté sombre. Si vous modifiez votre base de données, vous devez supprimer toutes les classes et l'ajouter à nouveau, ou simplement modifier les classes. null "ou la taille d'une chaîne. Mais si vous ajoutez des colonnes, je vous recommande de supprimer et d’ajouter les classes.

0

Une autre raison peut être l’erreur suivante: Si vous chargez des assemblys personnalisés avec Assembly.LoadFile contenant des fichiers edmx, ceux-ci ont déjà été chargés en mémoire. Cela crée des classes en double que le framework d'entité n'aime pas.

0
Thomas