【问题标题】:Generics and database - a design issue泛型和数据库 - 一个设计问题
【发布时间】:2011-11-04 18:59:19
【问题描述】:

情况是我有一个为实体建模的表。该实体有许多属性(每个属性由表中的一列标识)。问题是将来我需要添加新属性或删除一些属性。问题是如何对数据库和相应的代码(使用 C#)进行建模,以便在出现这种情况时很容易“拥有”一个新属性。

一开始只有一个属性,所以我只有一列。我在类中定义了相应的属性,具有适当的类型和名称,然后创建存储过程来读取和更新它。然后是第二个属性,快速复制粘贴,更改名称和类型以及一些 SQL,它就在那里。显然,这不是一个合适的模型。到这个时候,你们中的一些人可能会建议使用 ORM(EF 或其他),因为这会自动生成 SQL 和代码,但现在这对我来说不是一个选项。

我认为只有一个程序用于读取一个属性(按属性名称),另一个程序用于更新它(按名称和值),然后是一些通用程序,用于在同一语句中读取一个实体的一堆或所有属性。如果您考虑使用泛型,这在 C# 中可能听起来很容易,但数据库不知道泛型,因此不可能有一个强类型的解决方案。

我希望有一个“尽可能强类型”的解决方案,因此我不需要进行大量转换和解析。我会在代码中定义可用的属性,这样你就不会去猜测你有什么可用的并使用魔术字符串等。那么在系统中添加新属性的过程只意味着向表中添加新列并在代码中(例如在枚举中)添加新属性“定义”。

【问题讨论】:

  • 为什么不能使用EF?微软的天才们已经在这方面想通了,为你做了大量的工作。我不想看到你重新发明轮子。
  • 是的,我不明白你为什么需要避免使用 ORM。 (另外,我不知道 C# 泛型与这些有什么关系)
  • 我同意,但 EF 在架构方面还有更远的路要走,所以我现在还不能使用它。
  • “稍远一点”是什么意思?为什么不能使用它?
  • 我提到泛型是因为我仍然需要一些强类型的“感觉”。当您致电 GetProperty("PropertyName") 时,始终返回 Object 并没有多大帮助。

标签: c# sql-server generics strong-typing


【解决方案1】:

听起来你想这样做:

MyObj x = new MyObj();
x.SomeProperty = 10;

您为此创建了一个表,但您不想在添加时不断更改该表

x.AnotherProperty = "Some String";

你需要像这样规范化表格数据:

-> BaseTable
   RecordId, Col1, Col2, Col3

-> BaseTableProperty
   PropertyId, Name

-> BaseTableValue
   ValueId, RecordId, PropertyId, Value

你的班级应该是这样的:

 public class MyObj
 {
      public int Id { get; set; }
      public int SomeProperty { get; set; }
      public string AnotherProperty { get; set; }
 }

当您从 DL 创建对象时,您会枚举记录集。然后,您编写代码检查与您的配置同名的属性(BaseTableProperty.Name == MyObj.<PropertyName> - 然后在枚举记录集时尝试将类型转换为该类型。

然后,您只需在对象中添加另一个属性,在BaseTableProperty 中向数据库中添加另一条记录,然后您可以将那个人的值存储在BaseTableValue 中。

例子:

 RecordId
 ========
 1

 PropertyId          Name
 ==========          ====
 1                   SomeProperty

 ValueId     RecordId       PropertyId      Value
 =======     ========       ==========      =====
 1           1              1               100

您有两个结果集,一个用于基本数据,一个来自属性和值表。当您枚举每条记录时,您会看到 SomeProperty 的名称 - typeof(MyObj).GetProperty("SomeProperty") 是否存在?是的?它的数据类型是什么?诠释?好的,那么尝试通过设置属性将“100”转换为int:

 propertyInfo.SetValue(myNewObjInstance, Convert.ChangeType(dbValue, propertyInfo.PropertyType), null);

对于每个属性。

【讨论】:

  • 接近但我真的不想或不需要声明类中的每个属性。很少发生我一次需要多个属性的情况。大多数时候,我有对象 ID 并且只需要知道其中一个属性。这就是为什么我打算使用通用的GetProperty(int objectID, string propertyName) 方法。
  • 我会接受这个,因为它最接近我要采取的解决方案。
【解决方案2】:

即使你说你不能使用它们,这也是大多数 ORM 所做的。取决于您使用的是哪一个(或者如果它是一种学习体验,甚至可以创建),它们的复杂性和性能会有很大差异。如果您更喜欢轻量级 ORM,请查看 Dapper.Net。它也使用泛型,因此您可以检查代码,了解其工作原理,并在需要时创建自己的解决方案。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多