Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 从表中删除行,而不首先检查行是否存在_C#_.net_Sql Server_Datatable_Tableadapter - Fatal编程技术网

C# 从表中删除行,而不首先检查行是否存在

C# 从表中删除行,而不首先检查行是否存在,c#,.net,sql-server,datatable,tableadapter,C#,.net,Sql Server,Datatable,Tableadapter,我有一个WCF服务,它接受一个数据表,并将它们合并到现有数据中。以前,这只需要添加行,这很好地工作,但是随着删除行的新要求(无论它们是否实际存在),我遇到了一个问题 由于SQL server和数据表中的行数可能相当大,因此我不想加载现有行并将它们与我的数据表进行比较 我的代码执行以下操作: public Statistics ApplyChanges(DataTable changeData) { var stats = new Statistics(); if (change

我有一个WCF服务,它接受一个
数据表
,并将它们合并到现有数据中。以前,这只需要添加行,这很好地工作,但是随着删除行的新要求(无论它们是否实际存在),我遇到了一个问题

由于SQL server和
数据表
中的行数可能相当大,因此我不想加载现有行并将它们与我的
数据表
进行比较

我的代码执行以下操作:

public Statistics ApplyChanges(DataTable changeData)
{
    var stats = new Statistics();

    if (changeData.IsEmpty)
    {
         Trace.WriteLine(string.Format("Client {0} had nothing to do; called ApplyChanges anyway. (Should normally not happen.)", ClientId));
         return stats;
    }

    FooDataSet ds = new FooDataSet();
    ds.Bar.Merge(changeData, false, MissingSchemaAction.Ignore);

    foreach (var row in ds.Bar)
    {
        // This is the new requirement. If the incoming row's 'Value' is null,
        // delete the row from the database, or, if the row doesn't exist, do
        // nothing.
        if (row.Field<string>("Value") == null)
            row.Delete();
        else
            row.SetAdded();
    }

    int changesApplied;
    using (var scope = new TransactionScope())
    {
        BarTableAdapter barAdapter = new BarTableAdapter();
        changesApplied = barAdapter.Update(ds.Bar);
        scope.Complete();
    }

    stats.ChangesApplied = changesApplied;
    stats.ChangesFailed = ds.Bar.Count(r => r.HasErrors);

    Trace.WriteLine(string.Format("Client {0} applied {1} changes, had {2} changes fail.", ClientId, changesApplied, stats.ChangesFailed));

     return stats;
}
引发异常,
DBConcurrencyException
,并显示以下消息:“并发冲突:DeleteCommand影响了预期1条记录中的0条。”

我可以理解为什么当您关心并发性时,这是一个很好的通知,但我不需要这样做。我只想删除该行,或者忽略它丢失的部分。

根据本期文章,这是一篇很有帮助的文章。引述:

如果DataAdapter执行更新命令并检测到 受影响的行数为0,它会引发DBConcurrencyException。这个 整个更新操作将被中止,并且中不再有行 将检查数据集。通常情况下,会发生DBConcurrencyException 原因有两个:

  • 您错误地编写了自定义更新、插入或删除命令的SQL
  • 无法找到该行,因为用于查找该行的信息与当前值不匹配。此问题表示自上次检索信息以来,另一个用户已更改了该行
第二个是你想忽略的问题

处理错误有两种选择。一个选项是处理执行命令后但引发错误之前触发的
DataAdapter.RowUpdated
事件。您可以使用此事件处理程序记录问题,并以编程方式指示DataAdapter忽略错误并继续处理其他错误。下面是一个显示和跳过所有错误的示例:

protected void OnRowUpdated(object sender, SqlRowUpdatedEventArgs e) // handles DataAdapter.RowUpdated
{
    // Check how many records were affected. ' If no records were affected, there was an error. 
    if (e.RecordsAffected == 0) {
        // log?
        // Don't throw an exception, continue with following 
        e.Status = UpdateStatus.SkipCurrentRow;
    }
}
另一个更简单的选择是将
DataAdapter.ContinueUpdateOnError
属性设置为
true
。然后,在更新完成后,您可以调查错误、记录错误或向用户显示错误。
DataAdapter
将尝试每次更改

barAdapter.ContinueUpdateOnError = true; 

由于您使用的是强类型的
TableAdapter
,它只将
DataAdapter
保存为
protected
属性,因此无法直接更改此设置。您可以做的是扩展这个自动生成的类(它是一个
部分类
)。因此,在同一目录中创建另一个同名类,例如:
public partial class BarTableAdapter

现在,您可以创建新的属性或方法来访问
DataDapter
。请注意,该类必须位于相同的(自动生成的)命名空间中。例如:

namespace ApplicationName.DataSetNameTableAdapters
{
    public partial class BarTableAdapter 
    {
        public bool ContinueUpdateOnError
        {
            get
            {
                return this.Adapter.ContinueUpdateOnError;
            }
            set
            {
                this.Adapter.ContinueUpdateOnError = value;
            }
        }
    }
}
不要扩展原始类(
.designer.cs
),它将在设计器中的每次更改时被覆盖

现在您可以执行以下操作:

BarTableAdapter barAdapter = new BarTableAdapter();
barAdapter.ContinueUpdateOnError = true;
changesApplied = barAdapter.Update(ds.Bar);

你怎么知道它是否存在?只有数据库知道吗?我不在乎它是否存在。所以我想,是吗?问题是,运行SQL删除不存在的行(只会得到0个受影响的行)是完全合法的,这就是我想要的行为。你让我乐观了一秒钟。不幸的是,我处理的是
TableAdapter
,而不是
DataAdapter
。嗯,在
TableAdapter
中有一个底层
DataAdapter
,但是它的可见性是
受保护的内部
。幸运的是,
TableAdapter
是一个
部分类
,我可能可以通过自己的自定义属性访问它。我会试一试,然后再打给你。就像我说的,我会再打给你的。这很有魅力。非常感谢。
BarTableAdapter barAdapter = new BarTableAdapter();
barAdapter.ContinueUpdateOnError = true;
changesApplied = barAdapter.Update(ds.Bar);