この挿入と更新の動作は、通常、定義された主キーがないために発生します。テーブルに主キーを設定しましたか?これは、マージ時に列がどのようにマッチするかを示しています。 Per MSDN(強調鉱山):
にターゲットを新たなソースデータセットをマージし、そのまま の DataRowState値を有する任意のソース行が変更、または削除は、同じプライマリと ターゲット行に一致ありますキー 値。 のDataRowState値を持つソース行は、新しいターゲット行に一致する であり、 の同じ主キー値を新しいソース行として としています。
したがって、DataTable
ごとにPrimaryKey
propertyを設定する必要があります。私は数年前にこの詳細な例をMSDN DataTable.Merge
ページに書きました。あなたはここで書いてみることができます:Merge using Primary Keys for Expected Results。
このアプローチの簡単な例:
DataTable dt1 = new DataTable();
dt1.Columns.Add("ID", typeof(int));
dt1.Columns.Add("Customer", typeof(string));
dt1.PrimaryKey = new[] { dt1.Columns["ID"] };
dt1.Rows.Add(new object[] { 1, "Ahmad" });
DataTable dt2 = new DataTable();
dt2.Columns.Add("ID", typeof(int));
dt2.Columns.Add("Customer", typeof(string));
dt2.PrimaryKey = new[] { dt2.Columns["ID"] };
dt2.Rows.Add(new object[] { 1, "Mageed" });
// try without primary keys and it'll add a new record
dt1.Merge(dt2);
EDIT:あなたのコメントについて、あなたは本当に、以下のコードをテーブルを渡すことによって変化しなかったマージされた行の変更を拒否できます。 DataTable
を受け入れるメソッドはそれほど役に立ちません。 DataTable.AcceptChanges()
methodを呼び出す前にこのコードを使用することが重要です。そうしないと、行の状態は破棄されます。 LINQで
:LINQができない場合は
foreach (DataRow row in dt1.Rows)
{
if (row.RowState == DataRowState.Modified)
{
var original = dt1.Columns.Cast<DataColumn>()
.Select(c => row[c, DataRowVersion.Original]);
bool isUnchanged = row.ItemArray.SequenceEqual(original);
if (isUnchanged)
{
row.RejectChanges();
}
}
}
:
foreach (DataRow row in dt1.Rows)
{
if (row.RowState == DataRowState.Modified)
{
bool isUnchanged = true;
foreach (DataColumn col in dt1.Columns)
{
if (!row[col.ColumnName].Equals(row[col.ColumnName, DataRowVersion.Original]))
{
isUnchanged = false;
break;
}
}
if (isUnchanged)
{
row.RejectChanges();
}
}
}
これが行われた後、あなたはdt1.AcceptChanges()
を呼び出すことができます。
ありがとうございます、主キーが設定されるように更新しました。今、dt1とdt2がID = 100と同じエントリーを持つと仮定します。 dt2がdt1にマージされると、それは「変更済み」とマークされます。データが同じ場合、これらの "変更"を無視する方法はありますか? – John
@Johnは私の編集の解決策を見ています。 –