泛型和数据库 - 一个设计问题

发布于 2024-12-01 09:47:04 字数 565 浏览 1 评论 0原文

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

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

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

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

The situation is that I have a table that models an entity. This entity has a number of properties (each identified by a column in the table). The thing is that in the future I'd need to add new properties or remove some properties. The problem is how to model both the database and the corresponding code (using C#) so that when such an occasion appears it would be very easy to just "have" a new property.

In the beginning there was only one property so I had one column. I defined the corresponding property in the class, with the appropriate type and name, then created stored procedures to read it and update it. Then came the second property, quickly copy-pasted, changed name and type and a bit of SQL and there it was. Obviously this is not a suitable model going forward. By this time some of you might suggest an ORM (EF or another) because this will generate the SQL and code automatically but for now this is not an option for me.

I thought of having only one procedure for reading one property (by property name) and another one to update it (by name and value) then some general procedures for reading a bunch or all properties for an entity in the same statement. This may sound easy in C# if you consider using generics but the database doesn't know generics so it's not possible to have a strong typed solution.

I would like to have a solution that's "as strongly-typed as possible" so I don't need to do a lot of casting and parsing. I would define the available properties in code so you don't go guessing what you have available and use magic strings and the like. Then the process of adding a new property in the system would only mean adding a new column to the table and adding a new property "definition" in code (e.g. in an enum).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

演出会有结束 2024-12-08 09:47:04

听起来你想这样做:

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. - 然后尝试将类型转换为 。

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

BaseTableValue

 RecordId
 ========
 1

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

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

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

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

对于每个属性。

It sounds like you want to do this:

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

You have a table created for that, but you dont want to keep altering that table when you add

x.AnotherProperty = "Some String";

You need to normalize the table data like so:

-> BaseTable
   RecordId, Col1, Col2, Col3

-> BaseTableProperty
   PropertyId, Name

-> BaseTableValue
   ValueId, RecordId, PropertyId, Value

Your class would look like so:

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

When you create your object from your DL, you enumerate the record set. You then write code once that inspect the property as the same name as your configuration (BaseTableProperty.Name == MyObj.<PropertyName> - and then attempt the type cast to that type as you enumerate the record set.

Then, you simply add another property to your object, another record to the database in BaseTableProperty, and then you can store values for that guy in BaseTableValue.

Example:

 RecordId
 ========
 1

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

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

You have two result sets, one for basic data, and one joined from the Property and Value tables. As you enumerate each record, you see a Name of SomeProperty - does typeof(MyObj).GetProperty("SomeProperty") exist? Yes? What it it's data type? int? Ok, then try to convert "100" to int by setting the property:

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

For each property.

我家小可爱 2024-12-08 09:47:04

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

Even if you said you cannot use them, that is what most ORM do. Depending on which one you use (or even create if it's a learning experience), they will greatly vary in complexity and performance. If you prefer a light weight ORM, check Dapper.Net. It makes use of generics as well, so you can check the code, see how it works, and create your own solution if needed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文