根据自定义类动态调整Create Table和Insert Into语句

时间:2013-08-14 15:07:56

标签: c# ms-access oledb

好吧,这是与我试图删除的link相关的更大问题,但不能再这样了。人们说我不应该因为x问题link而发布部分问题,这是公平的。所以来了。

让我说我有一个班级:

 public class CustomClass
{
    public string Year;
    public double val;
    public string Tariff;
    public string ReportingGroup;
}

我现在有一些过程会创建一个带有结果的类的列表(实际上它是一个更大的类,但这不重要)。

我现在创建一个Access表,如果它还不存在的话。为此我需要类成员,理想情况下还需要类型(当前所有文本!):

public static void createtable(string path, string tablename, string[] columnnames)
    {
        try
        {
            string connectionstring = creadteconnectionstring(path);
            OleDbConnection myConnection = new OleDbConnection(connectionstring);
            myConnection.Open();
            OleDbCommand myCommand = new OleDbCommand();
            myCommand.Connection = myConnection;
            string columnam = "[" + columnnames[0] + "] Text";

            for (int i = 1; i < columnnames.Length; i++)
            {
                    columnam = columnam + ", [" + columnnames[i] + "] Text";
            }

            myCommand.CommandText = "CREATE TABLE [" + tablename + "](" + columnam + ")";
            myCommand.ExecuteNonQuery();
            myCommand.Connection.Close();
            Console.WriteLine("Access table " + tablename + " created.");
        }
        catch 
        {
                Console.WriteLine("Access table " + tablename + " already exists.");
                return;


        }


    }

注意列名实际上包含自定义类的类成员的名称。然后我将数据粘贴到其中:

        public static void appenddatatotable(string connectionstring, string tablename, string datstr, List<CustomClass> values)
    {
        string commandtext = "INSERT INTO " + tablename + " ([RunDate],[ReportingGroup], [Tariff], [Year], [Quarter]) VALUES(@RunDate, @ReportingGroup, @Tariff, @Year, @Quarter)";
        using (var myconn = new OleDbConnection(connectionstring))
        {
            myconn.Open();
            using (var cmd = new OleDbCommand())
            {

                foreach (var item in values)
                {
                    cmd.CommandText = commandtext;
                    if (string.IsNullOrEmpty(item.val))
                        item.val = "";
                    cmd.Parameters.Clear();
                    cmd.Parameters.AddRange(new[] { new OleDbParameter("@RunDate", datstr), new OleDbParameter("@ReportingGroup", item.RG), new OleDbParameter("@Tariff", item.tar), new OleDbParameter("@Year", item.yr), new OleDbParameter("@Quarter", item.val)});
                    cmd.Connection = myconn;
                    //cmd.Prepare();
                    cmd.ExecuteNonQuery();

                }
            }
        }

    }

一切正常。

然而,假设我在我的进程中改变了还需要另一个产生value2的计算,那么我需要更改类,createtable和teh appenddatatotable函数。我想只更新课程。

1 个答案:

答案 0 :(得分:2)

因此,您正在尝试为C#和MS Access数据库构建自己的ORM(对象关系映射器)。
虽然这是一项有趣的学习经历,但这是一个难以妥善解决的问题。

您需要做的是使用createtable中的反射来确定构造CREATE TABLE SQL语句所需的详细信息元数据(属性名称,属性类型)。 然后你可以使用类似DBUtils.CreateTable<CustomClass>(connStr);的东西来创建表格。

由于你没有在这个问题中提到反思,你真的需要首先尽可能多地学习它,并在你回答自己的问题之前先试验它。
您之前的问题已经使用反射提到了一些答案,并向您展示了如何获取任意类的属性名称和类型。

一旦遇到障碍,您将遇到其他问题:

  • 如何定义类型长度
    特别是对于字符串,在.Net中,它们几乎可以被认为是无限制的(无论如何大多数情况下使用),但在Access中,小于255个字符的字符串与较大字符串的字符串不同。

  • 如何定义主键。
    作为一般规则,数据库中的所有表必须具有主键字段,该字段用于以唯一方式标识表中的每个记录。
    在ORM中,它非常重要,因此您可以根据该密钥轻松获取数据,例如GetByID<CustomClass>(123)将返回包含主键CustomClass的记录中数据的ID实例是123。

  • 如何在数据库中定义索引 创建表格一切都很好,但您必须能够定义索引,以便查询具有预期的性能。

  • 如何定义表格之间的关系 数据库都是关于关系数据的,因此您需要一种方法在类中定义这些关系,以便类PurchaseOrder可以有PurchaseItem列表,并且您的代码可以理解例如,当您需要删除给定的采购订单时,您还需要删除数据库中的所有项目。

  • 如何只加载你需要的东西。
    假设您的Customer类具有PurchaseOrders属性,实际上是List<PurchaseOrders>。现在,如果您加载特定客户的数据,例如显示他们的电话号码,您不希望同时提取他们多年来所有可能的1,000或订单,其中每个可能有100个项目。 ..

  • 如何执行查询并使用其结果 将所有表格映射到类后,如何查询数据? linq很棒,但是很难自己实现,所以你需要一个很好的解决方案来允许你进行查询并允许你的查询返回有类型的数据。

对于其中许多问题,自定义属性是可行的方法,但随着您的移动并使您的ORM更加强大和灵活,它将增加复杂性,您的早期决策有时会让您失望并使事情进一步复杂化因为,让我们面对它,从头开始构建ORM,而有趣的体验,则很难。

所以,你真的必须考虑所有这些问题,并在进入兔子洞之前为你自己的系统设置一些限制。