6

我得到错误:

类型“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];

我知道这是错误的,但是有人可以告诉我如何正确地做到这一点而无需最好创建一个新对象吗?

4

7 回答 7

9

此查询的结果不是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();

或创建类...

于 2013-07-12T12:29:08.173 回答
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];
}
于 2013-07-12T12:48:18.140 回答
1

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

这里有几个问题。首先,在创建实例时,默认使用无参数构造函数。int[]没有可以调用的,这是您看到的错误。假设它确实有一个,我希望在尝试设置名为UserId.

正如其他人所回答的那样,解决此问题的一种简单方法是创建自己的课程。如果您想要一种不需要新类型的方法,您可以使用dapperQuery库中的非泛型类之类的东西(请参阅 Marc Gravell 在这篇文章中的回答)。实体框架似乎也使用和类提供了一些类似的功能,如此所示。ObjectQueryDbDataRecord

于 2013-07-12T12:27:05.693 回答
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();

在我的机器上工作...

于 2013-10-30T12:14:44.347 回答
0

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

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

要解决此问题,请将 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();

正如第一个解决方案所示......提供的许多解决方案可能具有完全相同的安全问题。

于 2016-10-24T17:26:50.657 回答
-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

于 2013-07-12T12:18:34.407 回答
-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(); 
}
于 2013-07-12T12:31:29.773 回答