上下文SqlQuery<>(),不详细说明所有列

时间:2015-04-19 22:29:53

标签: entity-framework

假设我有一个包含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查询中不存在的列,只映射可访问的列?

原因是,我有一些实体的列,有时我只想查询部分列。我不想为每个查询创建只包含必要列的新类。

2 个答案:

答案 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);
         }
    }                         
  }
}