Считыватель данных несовместим с указанной Entity Framework

У меня есть метод, который будет возвращать минимальные результаты из sproc, чтобы заполнить меню выбора. Когда я хочу получить минимальные результаты, я передаю bool getMin = true для sproc, а когда мне нужна полная запись, я передаю bool getMin = false.

Это вызывает ошибку Entity FrameWork "Читатель данных несовместим с указанным"

Наиболее значимая часть ошибки

{"Message":"Произошла ошибка.","ExceptionMessage":"Средство чтения данных несовместимо с указанным 'CatalogModel.proc_GetFramingSystems_Result'. Член типа FrameType не имеет соответствующего столбца в считыватель данных с тем же именем.","ExceptionType":"System.Data.EntityCommandExecutionException",

Очевидно, ошибка говорит мне, что, когда программа чтения данных пыталась установить свойство FrameType, которого не было в результатах запроса.

Теперь я понимаю ошибку, что я хочу знать, так это то, что я собираюсь разделить этот SQL-фрагмент на два пакета или есть способ обойти это?

Моя функция ниже

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;

3 ответа

Решение

Мне кажется, что обе ветви IF возвращают разные данные, первая ветка возвращает 9 столбцов, где вторая - только три. Я считаю, что EF не может отразить IFramingSystem от последнего. В частности, столбец FrameType (и 5 других столбцов) явно отсутствуют:

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

Я понимаю, что это старый пост; но я хотел поделиться тем, что узнал сегодня об этом. Я обнаружил, что "самая важная часть сообщения об ошибке" - это.

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

ожидает возвращения столбца из хранимой процедуры с псевдонимом FrameType.

Я столкнулся с этим, когда создал класс таблицы POCO (простой старый объект clr) с более дружественными для программиста именами. Вместо строго напечатанного имени, скажем, "email_address", я хотел "EmailAddy" и так далее. Я создал сопоставленный класс, указав это среди других сопоставленных столбцов.

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

Он генерировал ту же ошибку, за исключением того, что вместо FrameType он упоминал "EmailAddy". Исправление... Мне пришлось присвоить псевдониму столбца "email_address" в моей хранимой процедуре значение "EmailAddy", чтобы получить его для сопоставления возвращенного набора данных с моим POCO.

РЕДАКТИРОВАТЬ: я обнаружил, что это работает, только если ваш метод возвращает IEnumberable

public IEnumberable<myPOCO> GetMyPoco()

Вы получите то же сообщение об ошибке, если попытаетесь вернуть один объект POCO.

public myPOCO GetMyPoco()

Если вы вставляете / удаляете / обновляете (они рассматриваются EF как "незапрашиваемые") и могут быть вызваны нашим кодом с помощью

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

Но если вы делаете запрос select для необработанного оператора 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

Другие вопросы по тегам