1

以下に示すように、単一の FeeID の学生料金体系を含む 1 つのデータセットがあります。

        FeeID   Amount    FeeItem             Type
      *---------------------------------------------*
        10      7500      Admission Fee        T
        10      900       Annual Fee           T
        10      150       Application Fee      T
        10      850       Boy's Uniform        T
        10      50        Computer Fee         R

たとえば、次のデータを持つ別のデータセットがあります。

        FeeID   Amount    FeeItem             Type
      *---------------------------------------------*
        9       8500      Admission Fee        T
        9       950       Annual Fee           T
        9       150       Application Fee      T
        9       850       Boy's Uniform        T
        9       50        Computer Fee         R
        11      7500      Admission Fee        T
        11      900       Annual Fee           T
        11      150       Application Fee      T
        11      850       Boy's Uniform        T
        11      50        Computer Fee         R

最後の 3 つの列で構成されるセットが、FeeID が異なる可能性があるすべての料金構造のデータを含む別のデータセットに属しているかどうかを確認したいと考えています。実際 同じ料金構造を持つ一致する料金 ID を取得したい。

上記の例で、最初のものを 2 番目のもので検索すると、Trueが返され、一致する FeeID は11になります。

4

3 に答える 3

2

このトリックを使用できます

Dataset ds1
DataSet ds2
DataSet dest;
dest.Merge(ds1);
dest.AcceptChanges();
dest.Merge(ds2);
diff = destination.GetChanges()

差分が空かどうかを確認します

于 2012-09-04T14:12:14.640 に答える
1

編集:以下のコードにいくつかの改善を加えました。次DataTable.IndexOf(otherTable)の拡張メソッドは、テーブルが別のテーブルのサブセットであるかどうかをチェックします。

比較で無視する列名を渡すことができます。列の順序は重要ではありませんが、順序は重要ですDataRows(サブセットの行の順序は同じである必要があります)。

DataRowsの等しいサブセットが見つからなかった場合、または等しいサブセットが開始するメインテーブル(this拡張機能内)の最初のインデックスが見つからなかった場合は、-1を返します。

public static class DataTableExtensions
{
    public static int IndexOf(this DataTable tblMain, DataTable tblSub, params String[] ignoreColumns)
    {
        if (tblMain == null)
            throw new ArgumentNullException("tblMain");
        if (tblSub.Rows.Count == 0)
            throw new ArgumentException("tblSub must not be empty", "tblSub");

        if (tblSub.Rows.Count > tblMain.Rows.Count)
            return -1;

        IEnumerable<String> relevantColumnNames = tblSub.Columns.Cast<DataColumn>()
            .Select(c => c.ColumnName)
            .Except(ignoreColumns)
            .ToArray();

        foreach (String colName in relevantColumnNames)
            if (!tblMain.Columns.Contains(colName))
                return -1;

        for (int mainRowIndex = 0; tblMain.Rows.Count - mainRowIndex >= tblSub.Rows.Count; mainRowIndex++)
        {
            // check if current window is equal to tblSub
            bool allRowsAreEqual = true;
            for (int windowIndex = mainRowIndex; windowIndex < tblSub.Rows.Count + mainRowIndex; windowIndex++)
            {
                DataRow currentMain = tblMain.Rows[windowIndex];
                DataRow currentSub = tblSub.Rows[windowIndex - mainRowIndex];
                bool allFieldsAreEqual = relevantColumnNames.All(colName =>
                    Object.Equals(currentMain[colName], currentSub[colName]));
                if (!allFieldsAreEqual)
                {
                    allRowsAreEqual = false;
                    break; // continue with next window in main-table
                }
            }
            if (allRowsAreEqual)
                return mainRowIndex;
        }
        // no equal window found in main-table
        return -1;
    }
}

サンプルデータ:

var TblSub = new DataTable();
var TblMain = new DataTable();
TblSub.Columns.Add("FeeID", typeof(int));
TblSub.Columns.Add("Amount", typeof(int));
TblSub.Columns.Add("FeeItem", typeof(string));
TblSub.Columns.Add("Type", typeof(char));
TblMain.Columns.Add("FeeID", typeof(int));
TblMain.Columns.Add("Amount", typeof(int));
TblMain.Columns.Add("FeeItem", typeof(string));
TblMain.Columns.Add("Type", typeof(char));

TblSub.Rows.Add(10, 7500, "Admission Free", 'T');
TblSub.Rows.Add(10, 900, "Annual Fee", 'T');
TblSub.Rows.Add(10, 150, "Application Free", 'T');
TblSub.Rows.Add(10, 850, "Boy's Uniform", 'T');
TblSub.Rows.Add(10, 50, "Computer Free", 'R');

TblMain.Rows.Add(9, 8500, "Admission Free", 'T');
TblMain.Rows.Add(9, 950, "Annual Fee", 'T');
TblMain.Rows.Add(9, 150, "Application Free", 'T');
TblMain.Rows.Add(9, 850, "Boy's Uniform", 'T');
TblMain.Rows.Add(9, 50, "Computer Free", 'R');
TblMain.Rows.Add(10, 7500, "Admission Free", 'T');
TblMain.Rows.Add(11, 900, "Annual Fee", 'T');
TblMain.Rows.Add(11, 150, "Application Free", 'T');
TblMain.Rows.Add(11, 850, "Boy's Uniform", 'T');
TblMain.Rows.Add(11, 50, "Computer Free", 'R');

次のように使用できます。

int firstIndex = TblMain.IndexOf(TblSub, "FeeID");
if (firstIndex == -1)
    Console.Write("Second table does not contain first table");
else
    Console.Write("Second table does contain first table at row-index " + firstIndex);

出力は次のとおりです。

2番目のテーブルには、行インデックス5の最初のテーブルが含まれています


古いアプローチ

2つのDataTableが等しいかどうかをチェックする次のメソッドを使用できます。

using System.Linqを追加する必要がありますEnumerable.SequenceEqual。Linqを使用できない場合は、ループを使用してください。

static bool TablesEqual(DataTable table1, DataTable table2, params int[] skipColumns)
{
    if (table1.Rows.Count != table2.Rows.Count)
        return false;

    for (int i = 0; i < table1.Rows.Count; i++)
    {
        var array1 = table1.Rows[i].ItemArray
            .Where((obj, index) => !skipColumns.Contains(index));
        var array2 = table2.Rows[i].ItemArray
            .Where((obj, index) => !skipColumns.Contains(index)); ;
        if (!array1.SequenceEqual(array2))
        {
            return false;
        }
    }
    return true;
}

次のように、無視する列のインデックスを渡す必要があります。

bool allEqual = TablesEqual(t1, t2); // all equal
bool equalIgnore0 = TablesEqual(t1, t2, 0); // ignore first column
bool equalIgnore0and2 = TablesEqual(t1, t2, 0, 2); // ignore first and third column
于 2012-09-04T14:28:43.000 に答える
0

最後に、私はこの問題を解決することができます。以下は私の機能です。TimSchmelterが提供するTablesEqual関数を使用しています。この関数は、正の整数である有効なFeeIDを返します。一致するものが見つからない場合は、-1を返します。

private int MatchFeeID(DataTable Dt)
{
  DataTable mainDt = bl.GetDataSet("Select * From FeeMaster"); //assume this is a function that will return all the fee structures from database.

  var fids = (from row in mainDt.AsEnumerable().Distinct()
            group row by row.Field<string>("fid") into rowGroup
            select new
            {
              fid = rowGroup.Key
            });

  foreach (var fid in fids)
  {
    string id = fid.fid;

    DataTable t1 = new DataTable();
    DataTable t2 = new DataTable();

    DataRow[] dr1 = mainDt.Select(String.Format("fid = '{0}'", id));

    t1 = dr1.CopyToDataTable();
    t2 = Dt;

    bool res = TablesEqual(t1, t2, 0, 1);
    if (res) return Convert.ToInt32(id);
  }

  return -1;
}
于 2012-09-04T19:46:24.050 に答える