我有分布式数据库架构,其中数据存储在多个SQL服务器中。
如何通过运行单个查询来选择/更新/删除。例如,“select * from employees”应该从我拥有的所有数据库中返回数据。
如何编写跨多个SQL服务器运行的单个查询,并将单个统一视图添加到我的Web服务器。
注意:由于SQL服务器的数量可能会在不同的时间发生变化,因此我正在寻找除链接查询以外的其他内容,因为大规模(向上或向下)管理链接查询是一件很大的痛苦
答案 0 :(得分:6)
要与不同的数据库/连接通信,您需要通过TransactionScope进行分布式事务;幸运的是,这实际上比db-transactions 更容易(尽管你需要对System.Transactions.dll的引用):
using(TransactionScope tran = new TransactionScope()) {
// lots of code talking to different databases / connections
tran.Complete();
}
此外,TransactionScope
自然地嵌套,SqlConnection
自动登记,使其非常易于使用。
答案 1 :(得分:3)
如果您打开与范围内不同服务器的连接,则该事务将被转换为分布式事务。
示例:强>
using (TransactionScope scope = new TransactionScope())
{
conn1.Open(); //Open connection to db1
conn2.Open(); //Open connection to db2
// Don't forget to commit the transaction so it won't rollback
scope.Complete()
}
答案 2 :(得分:0)
这里最好的解决方案是使用虚拟DBMS将多个后端混合到一个明显的后端 - 因此您的查询将转到Virtual DBMS,然后将其适当地中继到实际的数据存储。
OpenLink Virtuoso是一种选择。 Virtuoso打开与任何ODBC可访问(包括JDBC可访问,通过ODBC-to-JDBC Bridge)数据源的连接。
您的数据消费应用程序可以根据需要通过ODBC,JDBC,OLE-DB或ADO.NET连接到Virtuoso。所有远程链接对象(表,视图,存储过程等)都可通过所有数据访问机制获得。
虽然您可以使用此处概述的其他技术获得类似的结果,但这些技术要求最终用户了解所有有关后端数据结构的信息,并自行优化查询。使用Virtuoso,内置的基于成本的优化器将重新编写查询,以最小的网络流量提供最快的结果,基于在远程对象中链接时构建的虚拟架构。
我希望这有帮助!
泰德
ObDisclaimer:我为OpenLink Software工作,但不会直接从任何选择使用我们产品的人那里获益。
答案 3 :(得分:0)
除非您愿意插入可能与其他服务器(可能使用SQL CLR)协调的某种类型的中介(例如SQL Express实例),否则您无法执行单个查询所需的操作。但那太乱了。
简单地发出一堆异步请求,然后在它们到达时将响应合并到单个DataTable(或等效的)中会容易得多。通过使用本机ADO.NET样式的异步调用,所有查询都可以并行发生。当然,您需要在将数据读入单个DataTable时使用锁定。
答案 4 :(得分:0)
如果没有访问权限或特权来创建链接服务器,并使用所有Sql Server的合并JOINed Query生成View,请在所有Sql Server实例的同一查询语句中填充结果,并进行结果的合并。循环抛出所有数据库连接,并将收集的数据添加到合并的收集数据结构中,在此示例中,我选择DataTable:
DataTable consolidatedEmployees = new DataTable();
foreach(ConnectionStringSettings cs in ConfigurationManager.ConnectionStrings)
{
consolidatedEmployees.Merge(
SelectTransaction("select * from employees", cs.ConnectionString));
}
使用此方法示例来查询基于ADO.NET的任何SQL Server数据库:
/// <summary>
/// Method to execute SQL Query statements with
/// Transaction scope using isolation level to select read commited data
/// </summary>
/// <param name="query">SQL Query statement</param>
/// <param name="connString">Connections String</param>
internal DataTable SelectTransaction(string query, string connString)
{
DataTable tableResult = null;
SqlCommand cmd = null;
SqlConnection conn = null;
SqlDataAdapter adapter = null;
TransactionOptions tranOpt = new TransactionOptions();
tranOpt.IsolationLevel = IsolationLevel.ReadCommitted;
using (TransactionScope scope = new TransactionScope(TransactionScopeOption.Required, tranOpt))
{
tableResult = new DataTable();
try
{
conn = new SqlConnection(connString);
conn.Open();
cmd = new SqlCommand(query, conn);
adapter = new SqlDataAdapter(cmd);
adapter.Fill(tableResult);
break;
}
catch (Exception ex)
{
scope.Dispose();
throw new Exception("Erro durante a transação ao banco de Dados.", ex);
}
finally
{
if (null != adapter)
{
adapter.Dispose();
}
if (null != cmd)
{
cmd.Dispose();
}
if (null != conn)
{
conn.Close();
conn.Dispose();
}
}
scope.Complete();
}
return tableResult;
}
使用此解决方案,仅需注意复制的数据,便需要在合并结果上做出明显的区分。