根据自定义类动态调整 Create Table 和 Insert Into 语句
Posted
技术标签:
【中文标题】根据自定义类动态调整 Create Table 和 Insert Into 语句【英文标题】:Dynamically adjust Create Table and Insert Into statement based on custom class 【发布时间】:2013-08-14 15:07:56 【问题描述】:好的,这是与link 相关联的更大问题,我试图删除但不能再删除。人们说我不应该因为 x y 问题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 和 appenddatatotable 函数。我只想更新课程。
【问题讨论】:
【参考方案1】:因此,您正在尝试为 C# 和 MS Access 数据库构建自己的 ORM(对象关系映射器)。 虽然这是一种有趣的学习体验,但它是一个很难正确解决的问题。
您需要做的是在createtable
中使用反射来确定构造CREATE TABLE
SQL 语句所需的详细元数据(属性名称、属性类型)。
然后你可以使用DBUtils.CreateTable<CustomClass>(connStr);
之类的东西来创建表格。
由于您在这个问题中没有提到反射,因此您确实需要首先尽可能多地了解它,并先进行试验,然后才能回答自己的问题。 您之前的问题有一些已经使用反射提到的答案,并向您展示了如何获取任意类的属性名称和类型。
一旦你跨过了那道坎,你就会遇到其他问题:
如何定义类型长度 特别是对于字符串,在 .Net 中它们几乎可以被认为是无限的(无论如何大多数情况下),但在 Access 中,少于 255 个字符的字符串与较大的字符串不同。
如何定义主键。
作为一般规则,数据库中的所有表都必须有一个主键字段,用于以唯一的方式标识表中的每条记录。
在 ORM 中,这非常重要,因此您可以轻松地根据该键获取数据,例如 GetByID<CustomClass>(123)
将返回您的 CustomClass
的实例,其中包含来自主键 ID
为 123 的记录中的数据。
如何在数据库中定义索引。 创建表很好很好,但是您必须能够定义索引,以便查询具有预期的性能。
如何定义表之间的关系。
数据库都是关于关系数据的,因此您需要一种在类中定义这些关系的方法,以便类PurchaseOrder
可以拥有PurchaseItem
列表,并且您的代码可以理解这种关系,例如当您需要删除给定的采购订单时,您还需要删除其在数据库中的所有项目。
如何只加载您需要的内容。
假设您有一个具有PurchaseOrders
属性的客户类,该属性实际上是List<PurchaseOrders>
。现在,如果您加载特定客户的数据,例如显示他们的电话号码,您不希望同时提取他们多年来所做的所有可能的 1,000 件或订单,每个订单可能有 100 件商品。 ..
如何执行查询并使用查询结果。 将所有表映射到类后,如何查询数据? linq 很棒,但是自己很难实现,所以你需要一个好的解决方案来允许你进行查询并允许你的查询返回类型化的数据。
对于这些问题中的许多问题,自定义属性是可行的方法,但随着您不断发展并使您的 ORM 更加强大和灵活,它会增加复杂性,并且您的早期决定有时会让您感到沮丧并使事情变得更加复杂因为,让我们面对现实吧,从头开始构建 ORM 虽然是一种有趣的体验,但很难。
因此,在跳入兔子洞之前,您确实必须考虑所有这些问题,并对系统需要/想要的内容设置一些限制。
【讨论】:
以上是关于根据自定义类动态调整 Create Table 和 Insert Into 语句的主要内容,如果未能解决你的问题,请参考以下文章
根据标签文本长度动态自定义 UITableViewCell 的高度