C# 在数据库中保存类类型的最佳方法?

C# 在数据库中保存类类型的最佳方法?,c#,database-design,types,C#,Database Design,Types,在数据库中用什么方法来表示“type” 我有一个基类Action,它由许多子类继承Action有Id、Name等成员,所有这些成员都对应于数据库中名为Action的表中的等效列。所以action表如下所示: id | name | type public abstract class Action { public enum Kind { ControlAction = 1, UpdateAction = 2, etc

在数据库中用什么方法来表示“type”

我有一个基类
Action
,它由许多子类继承
Action
Id
Name
等成员,所有这些成员都对应于数据库中名为
Action
的表中的等效列。所以
action
表如下所示:

id | name | type 
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; } } }
类型
列表示它是什么操作。在我的代码中,它们对应于从父
Action
派生的子类。现在,如何将类的类型保存到数据库中的类型字段中

db中的类型列可以是任何数据类型

选项:

  • action.GetType().ToString()另存为数据库中的字符串。并通过使用反射将类型的字符串表示形式转换为其原始类型,从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
    可能有点不可读。


  • 有更好的解决方案吗?

    我会从第三个解决方案开始,使用一个哈希表,因为它看起来确实是更干净的设计。我会将其管理委托给数据库

    毕竟,这不是关系数据库最擅长的,在两个实体之间创建关系(在您的例子中是操作和类型)吗?另一个优点是最终得到了规范化的模式(当然,到目前为止,类型表只有一列,即其名称,但是规范化允许您在将来需要时轻松地向类型添加其他属性,这就是为什么它作为一种设计更简洁的原因)

    模式应该是这样的:

    id | name | type 
    
    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; } } }
    
    行动表

    action_id(PK) | name | type_id (int, FK to Type table)
    
    type_id(PK) | type_name
    
    类型表

    action_id(PK) | name | type_id (int, FK to Type table)
    
    type_id(PK) | type_name
    
    现在,如果一个类的名称在将来发生更改,那么您就安全了(您的第一个字符串类型命题引起的担忧)。实际上,您所要做的就是更改相应的
    type
    表行中的
    type\u name
    值,并且所有
    Action
    行仍将通过
    type\u id
    链接到此行,该id在创建后不会更改(这里没有问题,因为它没有任何“业务意义”)

    并且您拥有3中的哈希表(类型
    表),格式可读,因为RDMBS负责管理哈希表的键(类型idPK)


    请注意,您不必将类绑定到与
    type\u id
    列对应的
    int
    值,而是通过查找类类型(
    type\u name
    )从
    type
    表中获取
    type\u id

    我将使用您的第一个选项并使用反射。您似乎更希望添加新的操作类型,而不是更改现有的类名,因此使用反射序列化类型的方便性更有用。
    然后,您就可以拥有一个实用程序类,用于序列化操作并从其类型字符串中恢复操作。

    我最终使用了选项2,但属性的混乱程度较低。大概是这样的:

    id | name | type 
    
    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; } } }
    
    最大的优点是(即使它意味着更多的键入),它强制执行一个与类类型关联的数值

    现在,类到int只是:

    非常快

    但要将int转换为类实例(或类类型),我必须创建每个子操作类型的实例,并比较其
    ActionType
    属性以匹配输入的int值。这将是缓慢的。但我可以缓存一些东西,让它更快。比如:

    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
    
    static只读字典)。我甚至可以通过

    好处:

  • 创建新类(无属性)时的麻烦更少

  • 强制将int绑定到类类型

  • 速度适中,缓存充足


  • 您正在尝试创建ORM吗?或者,您真的需要(对于边缘情况可能)将类类型信息保存在数据库中,以便其他应用程序可以重用吗?@edsioufi不,这与orm无关。每个子操作(如
    ControlAction
    UpdateAction
    等)都是由客户端创建的操作。每种操作类型都有自己的信息集,客户机需要这些信息。现在我需要一种方法将客户端创建的操作保存到数据库中。稍后,当我从db加载这些不同的操作时,我需要将
    ControlAction
    UpdateAction
    中分离出来。此外,使用字符串作为ActionType,检查类型表(如果ActionType已经存在)并改为使用id(如果不存在,则将其添加到类型表),您可以创建类似缓存的东西(用于缓存具有id的actiontype名称的字典)@edsioufi,我不确定它在类名更改时有什么帮助。类型表中的
    type\u name
    应该是什么?Jeroen提出了一个很好的观点,这就是你的意思吗?不,在编辑之后似乎是这样。我如何在type表中进行类型查找?如果
    type\u name
    只是类的
    type
    的字符串表示,那么这就是不起作用。@edsioufi我现在明白了。你说的是,如果类的名称更改,我必须在
    type\u coulmn
    中更改字符串名称。还不错。但我可能会实现更简单的东西:)@nawfal Cool:)。TBH这实际上是一个简单的关系数据库用例,您只需要一个连接来获取所有数据,一个查找来插入。当然是你的电话:)。班名可能会改变