我收到错误:
类型'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];
我知道这是错的,但有人可以告诉我如何正确地完成它而不需要创建新对象吗?
答案 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[]
,然后在其上设置名为UserId
,IPId
和GameId
的属性。
这里有一些问题。首先,在创建实例时,默认情况下使用无参数构造函数。 int[]
没有可以调用的,这是您看到的错误。假设它确实有一个,我希望在尝试设置名为UserId
的属性时实例化它后,此代码将失败。
解决这个问题的一个简单方法是创建自己的课程,正如其他人已经回答的那样。如果您想要一种不需要新类型的方法,可以使用dapper库中的非通用Query
类(参见Marc Gravell在this帖子中的回答) 。实体框架似乎也使用ObjectQuery
和DbDataRecord
类提供了一些类似的功能,如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;
答案 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();
}