Считыватель данных несовместим с указанной 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