Устройство чтения данных несовместимо с указанной инфраструктурой Entity Framework

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

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

Самая важная часть ошибки

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

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

Теперь я понимаю ошибку, я хочу знать, что я хочу, чтобы я разделил этот sql sproc на два sprocs или есть ли работа для этого?

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

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;

Ответ 1

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

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

Ответ 2

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

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

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

Я столкнулся с этим, когда создал класс POCO (простой старый clr-объект) моей таблицы с более удобными для программиста именами. Вместо строго типизированного имени say '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.

EDIT: Я обнаружил, что это работает только в том случае, если ваш метод возвращает IEnumberable

public IEnumberable<myPOCO> GetMyPoco()

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

public myPOCO GetMyPoco()

Ответ 3

Если вы вставляете/удаляете/обновляете (они рассматриваются 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 и проверяете записи.

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