C# 数据集插入奇数子记录
场景:在Windows Server 2012上使用SQL Server 2008 r2的数据集,包含一个主表和两个子表(销售、销售明细、付款)。此数据集为每个表上的每个插入、更新和删除操作调用不同的存储过程 错误:此例程工作正常,只是偶尔会:a)插入不在原始数据表中的子记录,或b)插入重复的子记录 我注意到,当我将生产数据库恢复到我的开发机器中,然后运行应用程序时,会发生此错误,并且第一个事务会得到一些不是我键入的详细信息记录。第二次恢复数据库时,错误没有发生 在保存这些事务时,SQL Server日志会显示一些死锁,但这种情况很少见 更新的例行程序是: (感谢Bonnie对交易的建议: )C# 数据集插入奇数子记录,c#,sql-server-2008,dataset,transactionscope,C#,Sql Server 2008,Dataset,Transactionscope,场景:在Windows Server 2012上使用SQL Server 2008 r2的数据集,包含一个主表和两个子表(销售、销售明细、付款)。此数据集为每个表上的每个插入、更新和删除操作调用不同的存储过程 错误:此例程工作正常,只是偶尔会:a)插入不在原始数据表中的子记录,或b)插入重复的子记录 我注意到,当我将生产数据库恢复到我的开发机器中,然后运行应用程序时,会发生此错误,并且第一个事务会得到一些不是我键入的详细信息记录。第二次恢复数据库时,错误没有发生 在保存这些事务时,SQL Ser
wincs
{
一班
{
SqlConnection-conn;
public int UpdateSales(dsetSales)
{
Int32 _newId=0;
SqlDataAdapter da=null;
SqlDataAdapter-daDetail=null;
使用(TransactionScope=Utils.GetTransactionScope())
{
尝试
{
conn.Open();
//准备适配器
da=getDA2updateSales(康涅狄格州);
daDetail=getDA2updateSalesDetail(conn);
//准备已删除、更改或添加的表
DataTable DeletedDetail=ds.SalesDetail.GetChanges(DataRowState.Deleted);
DataTable AddedDetail=ds.SalesDetail.GetChanges(DataRowState.Added);
DataTable ModifiedDetail=ds.SalesDetail.GetChanges(DataRowState.Modified);
//删除行
如果((DeletedDetail!=null))
daDetail.Update(DeletedDetail);
//主行
da.更新(ds,“销售”);
//换新身份证
_newId=ds.Sales[0].IdSale;
//更新详细信息行
if((modifiedDetaile!=null))
daDetail.Update(ModifiedDetail);
//添加新行
如果((AddedDetail!=null))
{
foreach(AddedDetail.Rows中的dsetSales.SalesDetailRow d)
{
d、 IdSale=\u newId;
}
数据细节更新(添加细节);
}
//付款表按上述方式处理
scope.Complete();
ds.AcceptChanges();
}
捕获(例外情况除外)
{
_newId=0;
}
最后
{
如果(连接状态!=连接状态已关闭)
康涅狄格州关闭();
}
返回_newId;
}
}
专用SqlDataAdapter getDA2updateSales(SqlConnection conn)
{
SqlDataAdapter da=新的SqlDataAdapter(“从销售中选择*,其中IdSale=@IdSale”,conn);
//准备命令
da.DeleteCommand=新的SqlCommand(“spd_销售”,康涅狄格州);
da.InsertCommand=新的SqlCommand(“spi_销售”,康涅狄格州);
da.UpdateCommand=新的SqlCommand(“spu销售”,康涅狄格州);
da.SelectCommand.CommandType=CommandType.Text;
da.SelectCommand.Parameters.Add(“@IdSale”,SqlDbType.Int,0,“IdSale”);
da.InsertCommand.CommandType=CommandType.StoredProcess;
//
Add(“@IdSale”,SqlDbType.Int,0,“IdSale”);
Add(“@IdClient”,SqlDbType.Int,0,“IdClient”);
//其他领域。。。
Add(“@new_id”,SqlDbType.Int,0,“IdVenta”).Direction=ParameterDirection.Output;
//
da.UpdateCommand.CommandType=CommandType.StoredProcess;
Add(“@IdSale”,SqlDbType.Int,0,“IdSale”);
Add(“@IdClient”,SqlDbType.Int,0,“IdClient”);
//其他领域。。。
da.DeleteCommand.CommandType=CommandType.StoredProcess;
da.DeleteCommand.Parameters.Add(“@IdSale”,SqlDbType.Int,0,“IdSale”);
da.InsertCommand.UpdatedRowSource=UpdateRowSource.Both;
da.InsertCommand.CommandTimeout=900;
da.UpdateCommand.CommandTimeout=900;
返回da;
}
专用SqlDataAdapter getDA2updateSalesDetail(SqlConnection conn)
{
SqlDataAdapter da=新SqlDataAdapter(“从SalesDetail中选择*,其中IdSale=@IdSale”,conn);
//准备命令
da.DeleteCommand=新的SqlCommand(“spd_SaleDetail”,康涅狄格州);
da.InsertCommand=newsqlcommand(“spi_SaleDetail”,conn);
da.UpdateCommand=新的SqlCommand(“spu_SaleDetail”,康涅狄格州);
da.SelectCommand.CommandType=CommandType.Text;
da.SelectCommand.Parameters.Add(“@IdSale”,SqlDbType.Int,0,“IdSale”);
da.InsertCommand.CommandType=CommandType.StoredProcess;
//
Add(“@IdSaleDetail”,SqlDbType.Int,0,“IdSaleDetail”);
Add(“@IdSale”,SqlDbType.Int,0,“IdSale”);
Add(“@IdProducto”,SqlDbType.Int,0,“IdProduct”);
da.InsertCommand.Parameters.Add(“@Qty”,SqlDbType.Money,0,“Qty”);
da.InsertCommand.Parameters.Add(“@Cost”,SqlDbType.Money,0,“Cost”);
//其他领域
da.InsertCommand.Parameters.Add(“@new_id”,SqlDbType.Int,0,“IdSaleDetail”).Direction=ParameterDirection.Output;
//
da.UpdateCommand.CommandType=CommandType.StoredProcess;
Add(“@IdSaleDetail”,SqlDbType.Int,0,“IdSaleDetail”);
Add(“@IdSale”,SqlDbType.Int,0,“IdSale”);
Add(“@IdProducto”,SqlDbType.Int,0,“IdPr
namespace SalesWinCS
{
class Class1
{
SqlConnection conn;
public int UpdateSales(dsetSales ds)
{
Int32 _newId = 0;
SqlDataAdapter da = null;
SqlDataAdapter daDetail = null;
using (TransactionScope scope = Utils.GetTransactionScope())
{
try
{
conn.Open();
// preparing adapters
da = getDA2updateSales(conn);
daDetail = getDA2updateSalesDetail(conn);
// prepare deleted, changed or added tables
DataTable DeletedDetail = ds.SalesDetail.GetChanges(DataRowState.Deleted);
DataTable AddedDetail = ds.SalesDetail.GetChanges(DataRowState.Added);
DataTable ModifiedDetail = ds.SalesDetail.GetChanges(DataRowState.Modified);
// delete rows
if ((DeletedDetail != null))
daDetail.Update(DeletedDetail);
// main row
da.Update(ds, "Sales");
// get new ID
_newId = ds.Sales[0].IdSale;
// updates Detail rows
if ((ModifiedDetalle != null))
daDetail.Update(ModifiedDetail);
// add new rows
if ((AddedDetail != null))
{
foreach (dsetSales.SalesDetailRow d in AddedDetail.Rows)
{
d.IdSale = _newId;
}
daDetail.Update(AddedDetail);
}
// payment table processed as above
scope.Complete();
ds.AcceptChanges();
}
catch (Exception ex)
{
_newId = 0;
}
finally
{
if (conn.State != ConnectionState.Closed)
conn.Close();
}
return _newId;
}
}
private SqlDataAdapter getDA2updateSales(SqlConnection conn)
{
SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM Sales WHERE IdSale = @IdSale ", conn);
// prepare commands
da.DeleteCommand = new SqlCommand("spd_Sales", conn);
da.InsertCommand = new SqlCommand("spi_Sales", conn);
da.UpdateCommand = new SqlCommand("spu_Sales", conn);
da.SelectCommand.CommandType = CommandType.Text;
da.SelectCommand.Parameters.Add("@IdSale", SqlDbType.Int, 0, "IdSale");
da.InsertCommand.CommandType = CommandType.StoredProcedure;
//
da.InsertCommand.Parameters.Add("@IdSale", SqlDbType.Int, 0, "IdSale");
da.InsertCommand.Parameters.Add("@IdClient", SqlDbType.Int, 0, "IdClient");
// other fields...
da.InsertCommand.Parameters.Add("@new_id", SqlDbType.Int, 0, "IdVenta").Direction = ParameterDirection.Output;
//
da.UpdateCommand.CommandType = CommandType.StoredProcedure;
da.UpdateCommand.Parameters.Add("@IdSale", SqlDbType.Int, 0, "IdSale");
da.UpdateCommand.Parameters.Add("@IdClient", SqlDbType.Int, 0, "IdClient");
// other fields...
da.DeleteCommand.CommandType = CommandType.StoredProcedure;
da.DeleteCommand.Parameters.Add("@IdSale", SqlDbType.Int, 0, "IdSale");
da.InsertCommand.UpdatedRowSource = UpdateRowSource.Both;
da.InsertCommand.CommandTimeout = 900;
da.UpdateCommand.CommandTimeout = 900;
return da;
}
private SqlDataAdapter getDA2updateSalesDetail(SqlConnection conn)
{
SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM SalesDetail WHERE IdSale = @IdSale", conn);
// prepare commands
da.DeleteCommand = new SqlCommand("spd_SaleDetail", conn);
da.InsertCommand = new SqlCommand("spi_SaleDetail", conn);
da.UpdateCommand = new SqlCommand("spu_SaleDetail", conn);
da.SelectCommand.CommandType = CommandType.Text;
da.SelectCommand.Parameters.Add("@IdSale", SqlDbType.Int, 0, "IdSale");
da.InsertCommand.CommandType = CommandType.StoredProcedure;
//
da.InsertCommand.Parameters.Add("@IdSaleDetail", SqlDbType.Int, 0, "IdSaleDetail");
da.InsertCommand.Parameters.Add("@IdSale", SqlDbType.Int, 0, "IdSale");
da.InsertCommand.Parameters.Add("@IdProducto", SqlDbType.Int, 0, "IdProduct");
da.InsertCommand.Parameters.Add("@Qty", SqlDbType.Money, 0, "Qty");
da.InsertCommand.Parameters.Add("@Cost", SqlDbType.Money, 0, "Cost");
// other fields
da.InsertCommand.Parameters.Add("@new_id", SqlDbType.Int, 0, "IdSaleDetail").Direction = ParameterDirection.Output;
//
da.UpdateCommand.CommandType = CommandType.StoredProcedure;
da.UpdateCommand.Parameters.Add("@IdSaleDetail", SqlDbType.Int, 0, "IdSaleDetail");
da.UpdateCommand.Parameters.Add("@IdSale", SqlDbType.Int, 0, "IdSale");
da.UpdateCommand.Parameters.Add("@IdProducto", SqlDbType.Int, 0, "IdProduct");
da.UpdateCommand.Parameters.Add("@Qty", SqlDbType.Money, 0, "Qty");
da.UpdateCommand.Parameters.Add("@Cost", SqlDbType.Money, 0, "Cost");
// ...
//
da.DeleteCommand.CommandType = CommandType.StoredProcedure;
da.DeleteCommand.Parameters.Add("@IdSaleDetail", SqlDbType.Int, 0, "IdSaleDetail");
da.InsertCommand.UpdatedRowSource = UpdateRowSource.Both;
da.InsertCommand.CommandTimeout = 900;
da.UpdateCommand.CommandTimeout = 900;
return da;
}
public class Utils
{
/// <summary>
/// The TransactionScoope that gets returned here is Required and IsolationLevel.ReadCommitted.
/// </summary>
/// <returns></returns>
public static TransactionScope GetTransactionScope()
{
return new TransactionScope(TransactionScopeOption.Required, new TransactionOptions(){IsolationLevel = IsolationLevel.ReadCommitted});
}
}
}