使用ExecuteQuery进行Linq SELECT

时间:2013-07-12 12:06:32

标签: c# asp.net sql linq

我收到错误:

  

类型'System.Int32 []'必须声明一个默认(无参数)构造函数,以便在映射期间构造。

使用代码:

var gamePlayRecord = db.ExecuteQuery<int[]>("SELECT UserID, IPID, GameID FROM ArcadeGames WHERE ID = " + gamePlayRecordID).Single();
var userID = gamePlayRecord[0];
var ipID = gamePlayRecord[1];
var gameID = gamePlayRecord[2];

我知道这是错的,但有人可以告诉我如何正确地完成它而不需要创建新对象吗?

7 个答案:

答案 0 :(得分:8)

此查询的结果不是int[],而是带有数字的一行。

不好的解决方案:用于每个数字:

int userID = db.ExecuteQuery<int>("SELECT UserID FROM ArcadeGames WHERE ID = " + gamePlayRecordID).Single();
int ipID = db.ExecuteQuery<int>("SELECT IPID FROM ArcadeGames WHERE ID = " + gamePlayRecordID).Single();
int gameID db.ExecuteQuery<int>("SELECT GameID FROM ArcadeGames WHERE ID = " + gamePlayRecordID).Single();

或创建SQL查询

db.ExecuteQuery<int>(@"
SELECT UserID FROM ArcadeGames WHERE ID = {0}
UNION ALL
SELECT IPID FROM ArcadeGames WHERE ID = {0}
UNION ALL
SELECT GameID FROM ArcadeGames WHERE ID = {0}", 
gamePlayRecordID).ToList();

或创建课程......

答案 1 :(得分:2)

我想我有点误解了这个问题。但正如@goric解释的那样:ORM映射器想要将结果映射到一个对象。如果你不想要一个对象或类而不是使用ORM映射器,而是使用基本的SqlDataReader。

SqlCommand command = new SqlCommand("SELECT UserID, IPID, GameID FROM ArcadeGames WHERE ID = " + gamePlayRecordID, connection);
SqlDataReader reader = command.ExecuteReader();
if (reader.Read())
{
  var userID = reader[0];
  var ipID = reader[1];
  var gameID = reader[2];
}

答案 2 :(得分:1)

ORM在检索SQL结果后,尝试创建您指定类型的新实例,然后在该类型上查找与查询中选择的列同名的属性。因此,在您的情况下,它会尝试创建一个新的int[],然后在其上设置名为UserIdIPIdGameId的属性。

这里有一些问题。首先,在创建实例时,默认情况下使用无参数构造函数。 int[]没有可以调用的,这是您看到的错误。假设它确实有一个,我希望在尝试设置名为UserId的属性时实例化它后,此代码将失败。

解决这个问题的一个简单方法是创建自己的课程,正如其他人已经回答的那样。如果您想要一种不需要新类型的方法,可以使用dapper库中的非通用Query类(参见Marc Gravell在this帖子中的回答) 。实体框架似乎也使用ObjectQueryDbDataRecord类提供了一些类似的功能,如here所示。

答案 3 :(得分:0)

这是和丑陋的黑客这样做:

var gamePlayRecord = db.ExecuteQuery<string>(
        "SELECT cast(UserID as nvarchar(10)) + ';' + cast(IPID as nvarchar(10)) + ';' + cast(GameID as nvarchar(10)) as a FROM ArcadeGames WHERE ID = " + gamePlayRecordID
    )
    .Single()
    .Split(';')
    .Select(i => int.Parse(i))
    .ToArray();

在我的机器上工作......

答案 4 :(得分:0)

不直接回答你的问题,但要注意安全......

您的代码可能容易受到SQL注入攻击,具体取决于gamePlayRecordID的值。

要修复,请将SQL查询参数化(或彻底验证输入,如果来自&#34;不受信任的&#34;来源):

db.ExecuteQuery<int>(@"
  SELECT UserID FROM ArcadeGames WHERE ID = {0}
  UNION ALL
  SELECT IPID FROM ArcadeGames WHERE ID = {0}
  UNION ALL
  SELECT GameID FROM ArcadeGames WHERE ID = {0}", 
  gamePlayRecordID).ToList();

正如第一个解决方案所示......提供的许多解决方案可能存在同样的安全问题。

答案 5 :(得分:-1)

它应该是这样的

  var gamePlayRecord = db.ExecuteQuery<ArcadeGames>(@"SELECT UserID, IPID, GameID FROM ArcadeGames WHERE ID = {0}", gamePlayRecordID).Single();

                var userID = gamePlayRecord.UserID;
                var ipID = gamePlayRecord.IPID;
                var gameID = gamePlayRecord.GameID;

代码参考取自http://msdn.microsoft.com/en-us/library/bb361109.aspx

答案 6 :(得分:-1)

我认为没有正确的方法,因为它想要将它映射到具有命名属性的对象。即使您能够实例化该数组,也无法尝试将其映射到命名字段。

如果您不想为它创建类,但对创建动态对象更感兴趣,可以查看dapper orm。通过nuget安装它。 你可以这样做:

using (var sqlConnection
        = new SqlConnection(connectionString))
{
    sqlConnection.Open();

    IEnumerable products = sqlConnection
        .Query("Select * from Products where Id = @Id",
                        new {Id = 2});

    foreach (dynamic product in products)
    {        
        ObjectDumper.Write(string.Format("{0}-{1}", product.Id, product.ProductName));
    }
    sqlConnection.Close(); 
}