【问题标题】:The data reader is incompatible with the specified Entity Framework数据读取器与指定的实体框架不兼容
【发布时间】:2013-09-18 10:04:57
【问题描述】:

我有一个方法可以从存储过程中返回最小的结果来填充选择菜单。当我想要最简单的结果时,我将 bool getMin = true 传递给存储过程,当我想要完整记录时,我传递 bool getMin = false。

这导致“数据读取器与指定的不兼容”的Entity FrameWork错误

错误中最相关的部分

{"Message":"发生错误。","ExceptionMessage":"数据读取器与指定的'CatalogModel.proc_GetFramingSystems_Result'不兼容。类型的成员'FrameType'没有对应的数据读取器中同名的列。","ExceptionType":"System.Data.EntityCommandExecutionException",

显然错误告诉我,当数据读取器尝试设置不在查询结果中的属性“FrameType”时。

现在我明白了这个错误,我想知道的是,我是不是要把这个 sql sproc 分成两个 sproc,还是有办法解决这个问题?

下面是我的功能

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

下面是我的 TSQL

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;

【问题讨论】:

标签: c# .net tsql entity-framework-4


【解决方案1】:

在我看来,IF 的两个分支都返回不同的数据,第一个分支返回 9 列,而第二个分支只有 3 个。我相信 EF 不能反映后者的 IFramingSystem。具体来说,FrameType 列(以及其他 5 列)明显缺失:

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

【讨论】:

  • 我就是这么想的。哦,好吧,至少值得一问。感谢您的帮助@Wiktor Zychla。
【解决方案2】:

我知道这是一篇旧帖子;但是,我想分享我今晚在这方面学到的东西。我发现“错误消息中最相关的部分正在说明”是这样的。

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

期望从存储过程返回一个别名为“FrameType”的列。

我在创建表的 POCO(普通旧 clr 对象)类时遇到了这个问题,该类具有对程序员更友好的名称。我想要的是“EmailAddy”等等,而不是一个强类型的名称“email_address”。我创建了一个映射类,在其他映射列中说明了这一点。

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

虽然这是 EF 的其他部分工作所必需的,但在执行 db.SqlQuery 时不会引用映射类。 所以,当下面的代码执行时

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

除了提到“EmailAddy”而不是“FrameType”之外,它产生了相同的错误。 修复...我必须将存储过程中的“email_address”列别名为“EmailAddy”,以使其将返回的数据集映射到我的 POCO。

编辑:我发现这仅在您的方法返回 IEnumberable 时才有效

public IEnumberable<myPOCO> GetMyPoco()

如果您尝试返回单个 POCO 对象,您将收到相同的错误消息。

public myPOCO GetMyPoco()

【讨论】:

    【解决方案3】:

    如果您正在插入/删除/更新(这些被 EF 视为“非查询”),并且可以由我们的代码调用

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

    但如果对原始 SQL 语句进行选择查询,则使用

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

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

    ()

    SqlQuery()函数,在EF中,由于奇怪的原因,抛出异常插入/删除/更新操作。 (抛出的异常是“类型的成员,在数据读取器中没有对应的同名列。”)但是如果您打开Sql Management Studio并检查条目,它实际上已经执行了操作。

    仅供参考http://www.entityframeworktutorial.net/EntityFramework4.3/raw-sql-query-in-entity-framework.aspx

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-09-19
      • 2017-12-31
      • 1970-01-01
      • 2020-11-13
      • 1970-01-01
      • 2021-02-28
      相关资源
      最近更新 更多