2

現在、データベースを動的に処理するデータベース ハンドラーを作成しようとしています。フィールドタイプ「String、int、bool、String」のクラスがあり、このクラスをテーブルに変換し、すべてのフィールドタイプをデータセットの「フィールド」に変換したいとしますか?

どうやってやるの?

また、「System.Data.DataSet」、「System.Data.DataTable」、「System.Data.DataRow」、およびそれを処理するある種のアダプターを継承するいくつかのクラスを作成できますか。

設計モードに入ってデータセットを作成するとき、コードを見たときにコードを理解するのが非常に難しいことを私は知っています。しかし、これらのオブジェクトを使用し、それらを処理するクラスを作成して、データベースを動的に「作成」できるようにすることは可能ではないでしょうか。「デザイナー ビュー」は得られませんが、Database.AddTable(new Table("Field1", "Field2, "Field3")) は、デザイナー モードでグラフィカルに行うのと同じようにする必要があります。

何か案は?

主なアイデアは、柔軟性があり、どのクラスを取得しても、このクラスのフィールド値の各オブジェクトをデータベース フィールドとして持つ行のテーブルに変換できるということです。

アップデート

これは私がこの 1 時間で作成した単純なクラスですが、正しい方法で考えていますか? *.mdf / *.sdf ファイルに DataSet を追加できるようにする必要があります。

public class DataAccess
{

    SqlConnection connection;
    DataSet dataSet;

    public DataAccess(String databaseName, String connectionStr)
    {
        dataSet = new DataSet(databaseName);
        connection = new SqlConnection(connectionStr);
    }

    public void AddTable<T>(String tableName)
    {
        dataSet.Tables.Add(new DBTable<T>(tableName));
    }

    public void AddRow<T>(String tableName, T row)
    {
        ((DBTable<T>)dataSet.Tables[tableName]).AddRow<T>(row);
    }

    public List<C> GetRows<T, C>(String tableName, String columnName)
    {
        return ((DBTable<T>)dataSet.Tables[tableName]).GetRow<C>(columnName);
    }

    public String GetXML()
    {
        return dataSet.GetXml();
    }

    #region METHOD PROPERTIES

    public int ColumnCount(String tableName)
    {
        for (int i = 0; i < dataSet.Tables.Count; i++)
        {
            if (dataSet.Tables[i].TableName == tableName)
            {
                return dataSet.Tables[i].Columns.Count;
            }
        }

        return 0;
    }

    #endregion


}

public class DBTable<T> : System.Data.DataTable
{
    public DBTable(String tableName) : base(tableName)
    {

        PropertyInfo[] properties = typeof(T).GetProperties();

        for (int i = 0; i < properties.Length; i++)
        {
            try
            {
                AddColumn(properties[i].Name, properties[i].PropertyType);
            }
            catch { }
        }

    }

    private void AddColumn(String name, Type t)
    {
        this.Columns.Add(new DataColumn(name, t, null, MappingType.Attribute));
    }

    public void AddRow<T>(T obj)
    {
        PropertyInfo[] properties = typeof(T).GetProperties();

        if (properties.Length == this.Columns.Count)
        {

            bool valid = true;

            for (int i = 0; i < properties.Length; i++)
            {
                if (properties[i].PropertyType != this.Columns[i].DataType)
                {
                    valid = false;
                }
            }

            if (valid)
            {
                object[] p = new object[this.Columns.Count];

                for (int i = 0; i < properties.Length; i++)
                {
                    p[i] = properties[i].GetValue(obj, null);
                }

                this.Rows.Add(p);
            }
        }
    }

    public List<T> GetRow<T>(String columnName)
    {

        List<T> objects = new List<T>();

        for (int i = 0; i < this.Rows.Count; i++)
        {
            objects.Add((T)this.Rows[i][this.Columns[columnName]]);
        }

        return objects;

    }
}
4

1 に答える 1

4

Petapocoライブラリは、あなたが探しているものですデータベースから POCO オブジェクトに、またはその逆にデータを簡単に保存および取得できます。

一般的なリストと LINQ のいくつかのビットについて調べる必要があるかもしれません: Petapoco アプローチはオブジェクトも使用しませDataSetDataTable

leppie が述べたように、これは質問に対する完全な答えではありません。したがって、クラスに一致する DataTable オブジェクトの作成は、次の方法で実現できます。

public static DataTable CreateDataTable<T>()
{
    var dt = new DataTable();

    var propList = typeof(T).GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);

    foreach(MemberInfo info in propList)
    {
        if(info is PropertyInfo)
            dt.Columns.Add(new DataColumn(info.Name, (info as PropertyInfo).PropertyType));
        else if(info is FieldInfo)
            dt.Columns.Add(new DataColumn(info.Name, (info as FieldInfo).FieldType));
    }

    return dt;
}

後でこの表に記入したい場合:

public static void FillDataTable<T>(DataTable dt, List<T> items)
{
    var propList = typeof(T).GetMembers(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);

    foreach(T t in items)
    {
        var row = dt.NewRow();
        foreach(MemberInfo info in propList)
        {
            if (info is PropertyInfo)
                row[info.Name] = (info as PropertyInfo).GetValue(t, null);
            else if (info is FieldInfo)
                row[info.Name] = (info as FieldInfo).GetValue(t);
        }
        dt.Rows.Add(row);
    }
}

DataTableオブジェクトの作成と入力を同時に行いたい場合は、両方の機能を 1 つの関数に混在させることもできます。

于 2012-05-03T10:11:29.927 に答える