【问题标题】:Bitfield With 3 States...?具有 3 个状态的位域...?
【发布时间】:2010-05-11 02:11:37
【问题描述】:

我正在尝试为我的 ASP.NET MVC 应用程序创建一个授权方案,其中使用枚举来设置权限。例如:

[Flags]
enum Permissions
{
    ReadAppointments = 1,
    WriteAppointments = 2 | ReadAppointments,
    ReadPatients = 4,
    WritePatients = 8 | ReadPatients,
    ReadInvoices = 16,
    WriteInvoices = 32 | ReadInvoices
    ...
}

但我不太喜欢这样,因为它确实没有明确说明 Write 总是包含 Read。

然后我意识到一个要求是用户可能没有访问权限,例如约会。

基本上,我想要一个具有 3 种状态的“位域”:无、只读、完整(读/写)。我想仍然使用枚举位域,因为它很容易存储在数据库中(作为整数)。也很容易查看是否设置了权限。

有没有人知道如何使用 Enum 轻松完成此操作...还是我走错了方向?

编辑:我真的想避免在数据库中存储权限定义,因为我真的希望事情可以改变,而不必在数据库端进行太多修改。很高兴知道大型应用程序如何做到这一点。

【问题讨论】:

  • 在低级别保持 4 个状态:无,x 但不是 Y,Y bot 不是 X、X 和 Y。此外,使用 1 移位而不是 1、2、4、8、16 0 位、1 位移位、1 位移位 2 位等

标签: c# asp.net-mvc bitmap


【解决方案1】:

我可能会使用单个枚举来覆盖每个区域(发票、患者、约会)的单独字段。

enum Permission { None, ReadOnly, ReadWrite };

对我来说,这更容易理解和管理,而且它不会结合一堆不相关的东西(我应该说“看似不相关”,因为我对你的应用一无所知)。

【讨论】:

  • 当然我也是这么想的,但是如何轻松地将每个字段的数据存储在数据库中。
  • 我会为这些事情使用三个单独的 tinyint 字段(sql server)——int 也可以,但比你需要的要大。
  • 好的,但是随着应用程序的增长,我必须继续向表中添加更多字段......这不是很好的 IMO。
  • 如果应用程序增长,您可能会添加许多新表和字段 - 这是增长过程的一部分。我认为这些多合一的位掩码字段在某些情况下很方便,但是当您开始将太多不同的东西打包到其中时会让人感到困惑。但我认为这更多是个人喜好,而不是对与错。
  • 但我认为,如果我必须为 ResetUserPassword 之类的权限创建一个字段,并且实际上只有一小部分人将此值设置为 true,那将是开销。这与每个用户的 一个 字段相比。
【解决方案2】:

值 0 是否意味着没有权限?即:

0 是不能修改预约、患者或发票

1是已读预约,但不能修改其他人

2是写约会,但不能修改别人

3是读/写约会,但不能修改别人

4是读取患者,但不能修改其他人。

如果你有...

51 那是:

读/写发票和读/写约会,但无权访问患者...

【讨论】:

    【解决方案3】:

    严格来说,一个位域不能有两个可能值以外的任何值,就像一个(十进制)数字不能有超过十个可能值一样。基数 2 表示两个值。

    除此之外,不要将特定于业务的权限存储为二进制值;你以后后悔。单独存放它们。随意使用位域来定义权限的细节(无/读/写/等),但不是权限本身的性质。

    为什么是这个社区 Wiki?

    【讨论】:

    • 当然我理解了一下只能取这两个值。我对解决这个问题的方法更感兴趣。编辑:一定是不小心点击了社区 Wiki……我怎样才能把它关掉?
    • @TheC 一旦你把它变成 CW 你就不能撤消它
    【解决方案4】:

    我借用并修改了这个例子:C# vs Java Enum (for those new to C#)

    不管我不会使用枚举,我都会使用一个可以提供更大灵活性的类。这样的事情可能会有所帮助,只是不要添加患者和发票,因为这与读写权限的问题正交变化。

    进行位操作的方法有很多种,可能应该在单独的代码层上完成。如果您需要对序列化(到文件或数据库)进行位操作,那么您应该将该代码放在那里。

    我不经常使用 C#,所以语法可能不正确,我主要使用 Java。无论如何,这里的基本概念应该很清楚:

    public class Permissions
    {
        public static readonly Permissions NONE = new PERMISSIONS("NONE",false,false);
        public static readonly Permissions READ = new PERMISSIONS("READ",true,false);
        public static readonly Permissions FULL= new PERMISSIONS("FULL",true,true);
    
        public static IEnumerable<Permissions> Values
        {
                get
                {
                        yield return NONE;
                        yield return READ;
                        yield return FULL;
                }
        }
    
        private readonly string name;
        private readonly boolean read;
        private readonly boolean write;
        private readonly int bits;
    
        Permissions(string name, boolean read,boolean write)
        {
                this.name = name;
                this.read = read;
                this.write= write;
                this.bits = bits;
        }
    
        public string Name { get { return name; } }
    
        // returns true if read permission is granted
        public double isReadable { get { return read; } }
    
        // returns true if write permission is granted
        public double isWriteable { get { return write; } }
    
        public override string ToString()
        {
                return name;
        }
    
        // returns bit field
        public int bits { get { return write ? 1 : 0 | read ? 2 : 0; } }
    }
    

    【讨论】:

      【解决方案5】:

      方向错误。您的应用程序将增长,然后位域将不再足够,您将进行大量返工。最好从一开始就“正确”。

      【讨论】:

      • 好吧,如果是错误的方向,你推荐什么作为“正确的”?
      猜你喜欢
      • 1970-01-01
      • 2016-08-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多