0

ストアド プロシージャを使用せずに多くの SQL 挿入を行う必要があります。

大きなクラスの場合、挿入文字列が巨大になるので、オブジェクトを渡すときにそれを処理する一般化された挿入関数を作成することを考えていました。以下に書いたものは機能しますが、(1) 可能なすべてのデータ型を指定する必要があり、(2) すべての値を文字列に変換して挿入文字列を作成する必要があるため、理想的ではありません。値。

オブジェクトクラスに渡す関数が必要であり、関数はオブジェクトの値をデータベースに挿入します(テーブル内のすべての列名がオブジェクトのプロパティ名と一致する場合)

どんなアイデアでも大歓迎です、ありがとう。

public static IEnumerable<KeyValuePair<string, T>> PropertiesOfType<T>(object obj)
{
    return from p in obj.GetType().GetProperties()
           where p.PropertyType == typeof(T)
           select new KeyValuePair<string, T>(p.Name, (T)p.GetValue(obj, null));
}

public string InsertString(string _table, object _class)
{
    Dictionary<string, string> returnDict = new Dictionary<string, string>();
    StringBuilder sb = new StringBuilder();
    foreach (var property in PropertiesOfType<DateTime>(_class))
        returnDict.Add(property.Key, property.Value.ToString("yyyy-MM-dd HH:mm:ss"));
    foreach (var property in PropertiesOfType<string>(_class))
        returnDict.Add(property.Key, property.Value);
    foreach (var property in PropertiesOfType<int>(_class))
    {
        if (property.Key == "Key")
            continue;
        returnDict.Add(property.Key, property.Value.ToString());
    }            
    foreach (var property in PropertiesOfType<bool>(_class))
    {
        if (property.Value)
            returnDict.Add(property.Key, "1");
        else
            returnDict.Add(property.Key, "0");
    }
    foreach (var property in PropertiesOfType<decimal>(_class))
        returnDict.Add(property.Key, property.Value.ToString());
    foreach (var property in PropertiesOfType<long>(_class))
        returnDict.Add(property.Key, property.Value.ToString());
    if (returnDict.Count == 1)
    {
        sb.Append(string.Format("INSERT INTO [{0}] ({1}) VALUES ('{2}')", _table, returnDict.ElementAt(0).Key, returnDict.ElementAt(0).Value));
    }
    else
    {
        for (int i = 0; i < returnDict.Count; i++)
        {
            if (i == 0)
                sb.Append(string.Format("INSERT INTO [{0}] ({1}, ", _table, returnDict.ElementAt(i).Key));
            else if (i == returnDict.Count - 1)
                sb.Append(string.Format("{0}) ", returnDict.ElementAt(i).Key));
            else
                sb.Append(string.Format("{0}, ", returnDict.ElementAt(i).Key));
        }
        for (int i = 0; i < returnDict.Count; i++)
        {
            if (i == 0)
                sb.Append(string.Format("VALUES ('{0}', ", returnDict.ElementAt(i).Value));
            else if (i == returnDict.Count - 1)
                sb.Append(string.Format("'{0}')", returnDict.ElementAt(i).Value));
            else
                sb.Append(string.Format("'{0}', ", returnDict.ElementAt(i).Value));
        }
    }        
    return sb.ToString();
}



string query = InsertString(_table, _obj);
4

1 に答える 1

1

私は、外部ライブラリやフレームワークを必要としない、非常に満足している方法を見つけることができました。

@HardikParmarの提案に基づいて、クラスオブジェクトをデータテーブルに変換する新しいプロセスを構築しました。これにより、関連するすべてのデータ型が列として保存されます。

次に、クラス オブジェクトを使用して構造化データテーブルに行を追加します。

これで、1 行の値を持つデータテーブルができました。

次に、PARAMATERIZED 挿入ステートメントを作成します。次に、コマンド テキストで値をパラメーターに追加します。

ほとんどきれいで、常に改善の余地があります。

//this function creates the datatable from a specified class type, you may exclude properties such as primary keys
public DataTable ClassToDataTable<T>(List<string> _excludeList = null)
{
    Type classType = typeof(T);
    List<PropertyInfo> propertyList = classType.GetProperties().ToList();

    DataTable result = new DataTable(classType.Name);

    foreach (PropertyInfo prop in propertyList)
    {
        if (_excludeList != null)
        {
            bool toContinue = false;
            foreach (string excludeName in _excludeList)
            {
                if (excludeName == prop.Name)
                {
                    toContinue = true;
                    break;
                }
            }
            if (toContinue)
                continue;
        }
        result.Columns.Add(prop.Name, prop.PropertyType);
    }
    return result;
}
//add data to the table
public void AddRow(ref DataTable table, object data)
{
    Type classType = data.GetType();
    string className = classType.Name;

    if (!table.TableName.Equals(className))
    {
        throw new Exception("DataTableConverter.AddRow: " +
                            "TableName not equal to className.");
    }
    DataRow row = table.NewRow();
    List<PropertyInfo> propertyList = classType.GetProperties().ToList();
    foreach (PropertyInfo prop in propertyList)
    {            
        foreach (DataColumn col in table.Columns)
        {
            if (col.ColumnName == prop.Name)
            {
                if (table.Columns[prop.Name] == null)
                {
                    throw new Exception("DataTableConverter.AddRow: " +
                                        "Column name does not exist: " + prop.Name);
                }
                row[prop.Name] = prop.GetValue(data, null);
            }
        }                        
    }
    table.Rows.Add(row);
}
//creates the insert string
public string MakeInsertParamString(string _tableName, DataTable _dt, string _condition=null)
{
    StringBuilder sb = new StringBuilder();
    sb.Append(string.Format("INSERT INTO [{0}] (", _tableName));
    for (int i = 0; i < _dt.Columns.Count; i++)
    {
        sb.Append(string.Format("{0}", _dt.Columns[i].ColumnName));
        if (i < _dt.Columns.Count - 1)
            sb.Append(", ");                
    }
    sb.Append(") VALUES (");
    for (int i = 0; i < _dt.Columns.Count; i++)
    {
        sb.Append(string.Format("@{0}", _dt.Columns[i].ColumnName));
        if (i < _dt.Columns.Count - 1)
            sb.Append(", ");
    }
    sb.Append(")");
    if (!string.IsNullOrEmpty(_condition))
        sb.Append(" WHERE " + _condition);
    return sb.ToString();
}
//inserts into the database
public string InsertUsingDataRow(string _tableName, DataTable _dt, string _condition = null)
{
    try
    {
        using (SQLiteConnection conn = new SQLiteConnection(_dbPath))
        {
            string query = MakeInsertParamString(_tableName, _dt, _condition);
            SQLiteCommand cmd = new SQLiteCommand(query, conn);
            foreach (DataColumn col in _dt.Columns)
            {
                var objectValue = _dt.Rows[0][col.ColumnName];                    
                cmd.Parameters.AddWithValue("@" + col.ColumnName, objectValue);
            }
            conn.Open();
            cmd.ExecuteNonQuery();
            conn.Close();                
        }
        //return MakeInsertParamString(_tableName, _dt, _condition);
        return "Success";
    }
    catch (Exception ex) { return ex.Message; }
}
于 2014-11-11T06:41:07.867 に答える