假设我有一个包含3列的Person
实体:
public PERSON {
public int OID { get; set; }
public string NAME { get; set; }
public string SURNAME { get; set; }
}
我想用原始SQL查询它,但没有指定所有列,所以我写道:
var query = "select NAME, SURNAME from PERSON";
var list = context.SqlQuery<PERSON>(query).ToList();
但它抛出异常:
System.Data.Entity.Core.EntityCommandExecutionException : The data reader is incompatible with the specified '...'. A member of the type, 'OID', does not have a corresponding column in the data reader with the same name.
所以它似乎试图映射所有列,如果有些列丢失,它会抛出。
有没有办法让它忽略原始SQL查询中不存在的列,只映射可访问的列?
原因是,我有一些实体的列,有时我只想查询部分列。我不想为每个查询创建只包含必要列的新类。
答案 0 :(得分:2)
我可以想到3个可能对你有用的选项。
选项1:重写您的查询并使用标准的Linq查询:
var persons = from p in context.Persons
select new PERSON
{
NAME = p.NAME,
SURNAME = p.SURNAME
};
选项2:为您不需要的列返回虚拟值
var query = "select 0 AS OID, NAME, SURNAME from PERSON";
var list = context.SqlQuery<AlmostPERSON>(query).ToList();
选项3:使用数据库中所需的列创建自己的中间类:
public class AlmostPERSON
{
public string NAME { get; set; }
public string SURNAME { get; set; }
}
var query = "select NAME, SURNAME from PERSON";
var list = context.SqlQuery<AlmostPERSON>(query).ToList();
您甚至可以将此中间类投影到标准实体上,如下所示:
var list = context.SqlQuery<AlmostPERSON>(query)
.Select(ap => new PERSON
{
NAME = ap.NAME,
SURNAME = ap.SURNAME
})
.ToList();
答案 1 :(得分:2)
找到了另一种可能的解决方案:将ADO.NET IDataReader与AutoMapper一起使用
public List<T> ExecuteFor<T>(string sql)
{
using (_connection = new OracleConnection(_connectionString))
{
_connection.Open();
using (var command = new OracleCommand(sql, _connection))
{
using (OracleDataReader reader = command.ExecuteReader())
{
Mapper.CreateMap<IDataReader, List<T>>();
return Mapper.Map<IDataReader, List<T>>(reader);
}
}
}
}