在数据库中保存类的最佳方法?
在数据库中表示“类型”的好方法是什么?
我有一个基类Action
,它由许多子类inheritance。 Action
具有Id
, Name
等成员,它们对应于名为action
的数据库中的表中的等效列。 所以action
表看起来像这样:
id | name | type
type
列表示它是什么动作。 在我的代码中,它们对应于从父Action
派生的子类。 现在如何将类的类型保存到数据库中的类型字段 ?
db中的type列可以是任何数据类型。
选项:
-
保存
action.GetType().ToString()
作为db中的字符串。 通过使用reflection将类型的字符串表示转换为其原始类型,从db获取操作类型。 但如果将来类名改变,这将是有问题的。 -
创建一个枚举来表示每个子类并通过
TypeAttribute
装饰,例如:public abstract class Action { public enum Kind { [Type(typeof(ControlAction))] ControlAction = 1, [Type(typeof(UpdateAction))] UpdateAction = 2, etc } public abstract Kind ActionType { get; } } public class ControlAction : Action { public override Kind ActionType { get { return Kind.ControlAction; } } } public class UpdateAction : Action { public override Kind ActionType { get { return Kind.UpdateAction; } } } //etc
这看起来不错,除了从这里开始每个类我必须创建一个枚举。 这感觉有点太多工作要做。
-
构建一个单独的静态哈希表
,将一个类绑定到一个
int
值。 可能有点难以理解。
有更好的解决方案吗?
我会从第3个解决方案中使用哈希表,因为它看起来似乎更清晰。 我会将其管理权委托给数据库!
毕竟,这不是关系数据库最擅长的,创建两个实体之间的关系(在你的情况下,行动和类型)? 其他优点是你最终得到一个规范化的模式(当然,到目前为止,类型表只有一列,即它的名称,但规范化允许你在将来需要时轻松地为类型添加其他属性,这就是为什么它作为一种设计更清洁)。
架构将是这样的:
行动表
action_id(PK) | name | type_id (int, FK to Type table)
输入表格
type_id(PK) | type_name
现在,如果将来某个类的名称发生更改,您将会感到安全(请注意您的第一个命题是字符串类型)。 实际上,您要做的就是更改相应Type
表行中的type_name
值,并且所有Action
行仍然会通过type_id
链接到此行,而type_id
在创建后永远不会更改(此处没有问题,因为它不包含任何“商业意义“)。
并且您以3的可读格式获得了哈希表( Type
表),因为RDMBS负责管理哈希表的键( type_id
PK)。
请注意,您不必将类绑定到与type_id
列对应的int
值,而是通过查找类型类型( type_name
)从Type
表中获取type_id
。
我最终使用了选项2,但属性较少。 像这样的东西:
public abstract class Action { public enum Kind { ControlAction = 1, UpdateAction = 2, etc } public abstract Kind ActionType { get; } } public class ControlAction : Action { public override Kind ActionType { get { return Kind.ControlAction; } } } public class UpdateAction : Action { public override Kind ActionType { get { return Kind.UpdateAction; } } }
这样做的最大优点是(即使它意味着更多的输入), 它强制将一个数值与类类型相关联 。
现在class to int只是 :
var value = (int)instance.ActionType;
非常快。
但是要将int转换为类实例(或类类型),我将不得不创建每个子操作类型的实例,并比较其ActionType
属性以匹配输入的int值。 这将是缓慢的。 但是我可以缓存一些事情并使其更快。 像这样的东西 :
static readonly Dictionary actionTypes = GetDefaultInstanceOfAllActions().ToDictionary(x => x.ActionType, x => x.GetType()); public static Action ToAction(this Action.Kind value) { return (Action)Activator.CreateInstance(actionTypes[value]); }
GetDefaultInstanceOfAllActions
一些reflection(一次)以获得所有类型的操作(我使用类似这样的答案 )。 我甚至可以通过表达式路径使实例化更快。
好处:
-
创建新类时没有麻烦(没有属性)。
-
强制将int绑定到类类型。
-
适度快速,适当的缓存。
我会选择第一个选项并使用reflection。 您似乎更有可能想要添加新的操作类型而不是更改现有的类名,因此使用reflection序列化类型的简便性更为有用。 然后,您可以只使用一个实用程序类来序列化操作并从其类型字符串中恢复它们。