web-dev-qa-db-fra.com

Le lecteur de données n'est pas compatible avec l'Entity Framework spécifié

J'ai une méthode qui retournera les résultats nus min d'un sproc pour remplir un menu de sélection. Lorsque je veux les résultats nus min, je passe bool getMin = true au sproc, et quand je veux l'enregistrement complet, je passe bool getMin = false.

Cela provoque l'erreur Entity FrameWork de "le lecteur de données est incompatible avec le spécifié"

La partie la plus pertinente de l'erreur

{"Message": "Une erreur s'est produite.", "ExceptionMessage": "Le lecteur de données est incompatible avec le 'CatalogModel.proc_GetFramingSystems_Result' spécifié. Un membre du type" FrameType "n'a pas de colonne correspondante dans le lecteur de données portant le même nom. "," ExceptionType ":" System.Data.EntityCommandExecutionException ",

De toute évidence, l'erreur me dit que lorsque le lecteur de données a tenté de définir la propriété "FrameType", elle ne figurait pas dans les résultats de la requête.

Maintenant, je comprends l'erreur, ce que je veux savoir, c'est que je vais avoir divisé ce sproc sql en deux sprocs ou y a-t-il un travail pour cela?

Ma fonction ci-dessous

public static IEnumerable<IFramingSystem> GetFramingSystems(int brandID, string frameType, string glazeMethod, bool getMin)
{
    using (CatalogEntities db = new CatalogEntities())
    {
        return db.proc_GetFramingSystems(brandID, frameType, glazeMethod, getMin).ToList<IFramingSystem>();
    };
}

Mon TSQL ci-dessous

ALTER proc [Catelog].[proc_GetFramingSystems]
@BrandID   INT,
@FrameType VARCHAR(26),
@GlazeMethod VARCHAR(7) ='Inside',
@getMin    BIT = 0
as
BEGIN
SET NOCOUNT ON;
IF @getMin =0
BEGIN
SELECT c.ID,c.Name,c.Descr,c.FrameType,c.isSubFrame,
       c.GlassThickness,c.GlassPosition,c.GlazingMethod,c.SillProfile
        from Catelog.Component c
WHERE c.MyType ='Frame' 
AND c.FrameType = @FrameType
AND c.GlazingMethod = @GlazeMethod
AND c.ID IN(
SELECT cp.ComponentID FROM Catelog.Part p JOIN
            Catelog.ComponentPart cp ON p.ID = cp.PartID
            WHERE p.BrandID = @BrandID
            )
            ORDER BY c.Name
END
ELSE
SELECT c.ID,c.Name,c.Descr
        from Catelog.Component c
WHERE c.MyType ='Frame' 
AND c.FrameType = @FrameType
AND c.GlazingMethod = @GlazeMethod
AND c.ID IN(
SELECT cp.ComponentID FROM Catelog.Part p JOIN
            Catelog.ComponentPart cp ON p.ID = cp.PartID
            WHERE p.BrandID = @BrandID
            )
            ORDER BY c.Name
SET NOCOUNT OFF;
END;

Pour moi, il semble que les deux branches de la IF renvoient des données différentes, la première branche renvoie 9 colonnes où la seconde - seulement trois. Je crois que l'EF ne peut pas refléter le IFramingSystem de ce dernier. Plus précisément, la colonne FrameType (et 5 autres colonnes) sont évidemment manquantes:

 ...
 SELECT c.ID,c.Name,c.Descr    <- where are the remaining columns
    from Catelog.Component c
 ...
14
Wiktor Zychla

Je comprends que c'est un ancien poste; mais, je voulais partager ce que j'ai appris ce soir à ce sujet. Ce que j'ai trouvé que la "partie la plus pertinente du message d'erreur indique" est la suivante.

db.proc_GetFramingSystems(brandID, frameType, glazeMethod, getMin).ToList<IFramingSystem>();

s'attend à ce qu'une colonne soit renvoyée de la procédure stockée avec l'alias de "FrameType".

Je suis tombé dessus lorsque j'ai créé une classe POCO (plain old clr object) de ma table avec des noms plus conviviaux pour les programmeurs. Au lieu d'un nom fortement tapé, par exemple "adresse_e-mail", je voulais "EmailAddy" et ainsi de suite. J'ai créé une classe mappée indiquant cela parmi d'autres colonnes mappées.

this.Property(t => t.EmailAddy).HasColumnName("email_address");

Bien que cela soit nécessaire pour que d'autres parties d'EF fonctionnent, la classe de mappage n'est pas référencée lors de l'exécution d'un db.SqlQuery. Ainsi, lorsque le code ci-dessous s'exécute

var a = new SqlParameter("@fshipno", shipno);
return _context.db.SqlQuery<EmailList>("exec spGetEmailAddy @fshipno", a).ToList();

Il a généré la même erreur sauf qu'au lieu de "FrameType", il a mentionné "EmailAddy". Le correctif ... J'ai dû alias la colonne 'email_address' de ma procédure stockée en 'EmailAddy' pour qu'il mappe l'ensemble de données retourné à mon POCO.

EDIT: J'ai trouvé que cela ne fonctionne que si votre méthode retourne un IEnumberable

public IEnumberable<myPOCO> GetMyPoco()

Vous obtiendrez le même message d'erreur si vous essayez de renvoyer un seul objet POCO.

public myPOCO GetMyPoco()
10
midohioboarder

Si vous insérez/supprimez/mettez à jour (ceux-ci sont considérés par EF comme "sans requête") et peuvent être appelés par notre code à l'aide de

MyDbContext.Database.ExecuteSqlCommand(insert into Table (Col1,Col2) values (1,2));

Mais si vous effectuez une requête de sélection pour une instruction SQL brute, utilisez

MyDbContext.DbSet<Table_name>.SqlQuery(select * from table_name).ToList();

ou

MyDbContext.Database.SqlQuery(select * from table_name).ToList();

()

La fonction SqlQuery(), dans EF, pour des raisons étranges, déclenche une opération d'insertion/suppression/mise à jour d'exception. (L'exception levée est "Un membre du type n'a pas de colonne correspondante dans le lecteur de données avec le même nom.") Mais il a en fait effectué l'opération si vous ouvrez votre Sql Management Studio et vérifiez les entrées.

FYI http://www.entityframeworktutorial.net/EntityFramework4.3/raw-sql-query-in-entity-framework.aspx

1
Avinash Goud N J