使用ADO.NET和SQL服务器,如何一次获取两个表的数据行(快照)?
Using ADO.NET and SQL Server, how to fetch datarows of two tables at once (snapshot)?
使用 ADO.NET,是否可以同时从两个表中获取数据行?
和现在一样,分两步完成:
DataTable log = GetDataTable("select * from Log");
DataTable logDetail = GetDataTable("select * from LogDetail");
问题在于两次调用之间的数据可能会发生变化(例如:我们获取所有日志记录,同时在数据库中创建了一些新日志和详细信息,然后我们获取详细信息:一些详细信息没有关联的日志)。
一个可能的解决方案是在两个表之间进行一个连接的查询:
select *
from Log
inner join LogDetail on Log.Id = LogDetail.RefLog
现在只有一个调用,但还有另一个问题:每个日志详细信息的日志数据都是重复的,这意味着将有更多的数据传输(这两个表已经很大)
还有其他解决方案吗
亲爱的,如果你想在一个查询中包含它们,这可以通过多种方式实现,我看到你正在使用 ADO.NET,所以你需要一个 SQL 查询。现在你有两个表,你遇到了一个问题,一个 "Log" 记录可能有多个 "LogDetails" 记录。
如果你想创建一个 SQL 查询,你可以通过以下方式实现:
SELECT *
FROM LogDetails
INNER JOIN Log on LogDetails.RefLog = Log.Id
您将获得一个 LogDetails 对象列表,之后您可以按 "Log" 字段(例如,Id、名称等)对它们进行分组,最后您将获得一个日志对象列表和包含日志详细信息列表的每个对象。希望有所帮助^^
您可以在一条命令中将两个查询发送到 sql 服务器(正如 Khanh TO 在评论中提到的那样),只需填写 dataset
:
DataSet ds = new DataSet();
using(SqlConnection con = new SqlConnection("ConnectionString")
{
SqlCommand cmd = new SqlCommand("select * from Log; select * from LogDetail", con);
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(ds);
}
这将导致 ds
有 2 个数据表 - 每个查询一个。
注意:这里直接写代码,没有测试,可能会有一些错误。
可以使用SNAPSHOT transaction isolation level吗?
如果是,那么答案可以通过事务扩展:
var ds = new DataSet();
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
var command = connection.CreateCommand();
var transaction = connection.BeginTransaction(IsolationLevel.Snapshot);
command.Transaction = transaction;
command.CommandText = "select * from Log; select * from LogDetail";
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(ds);
transaction.Commit();
}
当前事务启动后其他事务对数据的修改对当前事务中执行的语句是不可见的。效果就好像事务中的语句获得了事务开始时存在的已提交数据的快照。 (from here)
使用 ADO.NET,是否可以同时从两个表中获取数据行?
和现在一样,分两步完成:
DataTable log = GetDataTable("select * from Log");
DataTable logDetail = GetDataTable("select * from LogDetail");
问题在于两次调用之间的数据可能会发生变化(例如:我们获取所有日志记录,同时在数据库中创建了一些新日志和详细信息,然后我们获取详细信息:一些详细信息没有关联的日志)。
一个可能的解决方案是在两个表之间进行一个连接的查询:
select *
from Log
inner join LogDetail on Log.Id = LogDetail.RefLog
现在只有一个调用,但还有另一个问题:每个日志详细信息的日志数据都是重复的,这意味着将有更多的数据传输(这两个表已经很大)
还有其他解决方案吗
亲爱的,如果你想在一个查询中包含它们,这可以通过多种方式实现,我看到你正在使用 ADO.NET,所以你需要一个 SQL 查询。现在你有两个表,你遇到了一个问题,一个 "Log" 记录可能有多个 "LogDetails" 记录。
如果你想创建一个 SQL 查询,你可以通过以下方式实现:
SELECT *
FROM LogDetails
INNER JOIN Log on LogDetails.RefLog = Log.Id
您将获得一个 LogDetails 对象列表,之后您可以按 "Log" 字段(例如,Id、名称等)对它们进行分组,最后您将获得一个日志对象列表和包含日志详细信息列表的每个对象。希望有所帮助^^
您可以在一条命令中将两个查询发送到 sql 服务器(正如 Khanh TO 在评论中提到的那样),只需填写 dataset
:
DataSet ds = new DataSet();
using(SqlConnection con = new SqlConnection("ConnectionString")
{
SqlCommand cmd = new SqlCommand("select * from Log; select * from LogDetail", con);
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(ds);
}
这将导致 ds
有 2 个数据表 - 每个查询一个。
注意:这里直接写代码,没有测试,可能会有一些错误。
可以使用SNAPSHOT transaction isolation level吗?
如果是,那么
var ds = new DataSet();
using (SqlConnection connection = new SqlConnection(connectionString))
{
connection.Open();
var command = connection.CreateCommand();
var transaction = connection.BeginTransaction(IsolationLevel.Snapshot);
command.Transaction = transaction;
command.CommandText = "select * from Log; select * from LogDetail";
SqlDataAdapter da = new SqlDataAdapter(cmd);
da.Fill(ds);
transaction.Commit();
}
当前事务启动后其他事务对数据的修改对当前事务中执行的语句是不可见的。效果就好像事务中的语句获得了事务开始时存在的已提交数据的快照。 (from here)