无法将原始SQL查询映射到DataRow

时间:2013-10-02 22:41:22

标签: linq entity-framework datarow

我想从下面的linq查询中获取IEnumerable。我做错了什么?

IEnumerable<DataRow> results = 
    context.Database.SqlQuery<DataRow>("SELECT * FROM Customer").AsEnumerable();

2 个答案:

答案 0 :(得分:3)

DataRow类没有默认(无参数)构造函数,因此您不能将其用作查询参数类型。类型参数没有通用约束,MSDN(!)上没有提及,但如果参数类型没有默认构造函数,列映射工厂将抛出异常:

  

结果类型'System.Data.DataRow'可能不是抽象的,必须   包括默认构造函数。

这是抛出此异常的代码:

internal static CollectionColumnMap CreateColumnMapFromReaderAndClrType(
    DbDataReader reader, Type type, MetadataWorkspace workspace)
{
      BindingFlags flags = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
      ConstructorInfo constructor = type.GetConstructor(flags, (Binder) null, Type.EmptyTypes, (ParameterModifier[]) null);
      if (type.IsAbstract || (ConstructorInfo) null == constructor && !type.IsValueType)
          throw EntityUtil.InvalidOperation(InvalidTypeForStoreQuery((object) type));
      // ...
}

BTW 映射到DataRow是没有意义的,即使它有默认的公共构造函数。因为它不是简单的基本类型,并且它没有与查询返回的列名相匹配的属性(是的,映射仅使用属性)。

正确使用Linq

IEnumerable<Customer> results = context.Customers;

这将生成SELECT * FROM Customer查询,并将查询结果映射到客户实体。如果你真的想使用原始SQL:

IEnumerable<Customer> results = 
     context.Database.SqlQuery<Customer>("SELECT * FROM Customers");

答案 1 :(得分:0)

我认为我们正试图解决同样的问题(无论如何,Google引领我到这里)。我正在通过SqlQuery<TElement>(string sql, params object[] parameters执行原始SQL命令,并希望在单元测试中断言从查询返回的结果的各个属性。

我打电话给方法:

var result = (db.SqlQuery<Customer>("select * from customers").First();

并验证了它返回的数据:

Assert.AreEqual("John", result.FirstName);

我在我的测试类中定义了一个私有类Customer(不幸的是,我没有使用实体框架):

private class Customer
{
    public string FirstName { get; set; }
}

Customer的属性必须与SQL查询中返回的列名匹配,并且它们必须是属性(而不仅仅是Customer类的变量。您不必为所有的属性创建属性从查询返回的列。