C#:仅在运行时知道数据库名称和列名称时,将数据库映射到类属性

时间:2018-06-22 14:23:41

标签: c# sql database linq

我目前有一个程序可以与数据库交互并从中查询数据。但是,我想弄清楚如何获取数据库和配置文件并将表内容映射到现有内容。

例如: 我有班人。一个人有一个ID(长),accountName(字符串),Title(字符串),firstName(字符串)和lastName(字符串)。

新连接的数据库具有与Person相同的属性,但以不同的方式存储它们。他们可能将表称为Individual,其中包含UniqueID(long),accName(string),personalTitle(string),fName(string),lName(string)列。

我从配置文件中知道与属性等效的每一列的名称,但是我只能在运行时读取它。有没有一种方法可以阅读我要查找的标题并将它们加载到这些类中,从而使我不必每次都对其进行硬编码?

谢谢!

4 个答案:

答案 0 :(得分:1)

是真的总是随机创建新数据库还是数量有限? 您可能有一个包含所有可能情况的类,但将“即时”检查应使用还是不使用哪种情况。

我还没有尝试使用任何ORM,但是我记得在处理XML序列化/反序列化时,前缀为“ bool ShouldSerializeXXXXXX”,也许与您的情况相同。

答案 1 :(得分:1)

我想到的最好的想法是跳过任何形式的ORM,而仅使用查询字符串:

假设我们只使用普通的ADO this way

您的查询字符串应类似于:

string queryString =
        $"SELECT {ConfigurationManager.AppSettings[productColumn]}
 , {ConfigurationManager.AppSettings[PriceColumn]} 
 , {ConfigurationManager.AppSettings[productNameColumn]} 
 from dbo.{ConfigurationManager.AppSettings[ProductTableName]} "
            + "WHERE {ConfigurationManager.AppSettings[UnitPriceColumn]}  > @pricePoint "
            + "ORDER BY {ConfigurationManager.AppSettings[UnitPriceColumn]}  DESC;";

感觉有点奇怪,但要求也是如此。

答案 2 :(得分:0)

这很容易实现。当过程返回数据表时,您将从配置文件中读取映射,并根据使用反射将哪些字段名称映射到该属性来设置类属性的值。

这是您可以使用的一些代码。

/// Your result objects list
List<DBObject> result = new List<DBObject>();
System.Reflection.ConstructorInfo ci = objectType.GetConstructor(new Type[] { });
System.Reflection.PropertyInfo[] props = objectType.GetProperties();
if ((table != null) && (table.Rows.Count > 0) && (ci != null) && (props != null) && (props.Length > 0))
{
    for (int i = 0; i < table.Rows.Count; i++)
    {
        DBObject dob = (DBObject)ci.Invoke(new object[] { });
        if (dob != null)
        {
            foreach (System.Reflection.PropertyInfo pi in props)
            {
                /// This is your method to get DB column name from config file
                string dbColumnName = GetDBColumnFromMappingConfigFile(pi.Name);
                object value = null;
                if (table.Columns.Contains(dbColumnName))
                {
                    if (table.Rows[i][dbColumnName] != DBNull.Value)
                    {
                        value = table.Rows[i][dbColumnName];
                    }
                }
                if (value != null)
                {
                    if ((pi.PropertyType.IsGenericType) && (pi.PropertyType.GetGenericTypeDefinition().Equals(typeof(Nullable<>))))
                    {
                        Type t = pi.PropertyType.GetGenericArguments()[0];
                        if (t != null)
                        {
                            object val = Convert.ChangeType(value, t);
                            pi.SetValue(dob, val, null);
                        }
                    }
                    else
                        pi.SetValue(dob, Convert.ChangeType(value, pi.PropertyType), null);
                }
            }
        }
    }
}

我通常使用PropertyAttributes代替Property名称,因为属性允许您定义默认值,以防DB值为NULL,定义设置器等。

答案 3 :(得分:0)

可以通过两种方式完成,您可以通过应用程序,数据库或组合方式完成

应用程序端

  1. 对程序类进行硬编码并在其上构建应用程序。
  2. 构建查询以基于已知查询填充类。
  3. 在应用程序中构建一个配置部分,以选择针对哪个类的哪个查询
  4. 使用该配置填充模型

Database Side稍微复杂一点,但最终在应用程序中变得更干净。您仍然可以正常创建类。

在数据库服务器上,有很多选项。 您仍然在应用程序中创建类和查询

  1. 您将在存储过程中执行所有CRUD操作,这些操作可以确定表是否存在;然后只需遍历 IF存在(选择表名...)的堆栈即可确定要运行哪个查询
  2. 您有一个“ setup”存储过程,该过程将存在的表转换为与您的应用程序类对齐的结构
  3. 和许多其他选项