The bitmask (flags) will enumerate beyond 64 with a bitarray with a logical grouping stored in the database

The first answer to this question: What to do when the enum bitmask (flags) gets too large - this is exactly what I'm trying to do, only I don’t know how to save it to the database using LINQ to SQL and bind it to users without creating two tables for each thing / logical group.

This is best explained with code (this is LinqPad friendly, albeit incomplete):

// Requirements: // 1) Using LINQ to SQL // 2) Track User CRUD rights in different parts of an application (parts referred to below as 'Things') // For example: ThingA.Create, ThingB.Read, ThingB.Update, ThingC.Delete // Desired usage: if (User.IsAllowed(ThingA.Create)) { // allowed } else { // not allowed } // 3) Allow for more than 64 'Things' // 4) Do not want to refer to permissions using strings like User.IsAllowed("Create ThingA"); // // Scenario A: This works, but you would be limited to adding only 60 'Things' // Example usage: // User Bob = new User(); // var desiredPermissions = Permissions.Create | Permissions.ThingA; // Permission = Unique binary value combination of flags // if ((Bob.Permissions & desiredPermissions) == desiredPermissions) { // Bob has permission to Create ThingA [Flags] public enum Permissions : ulong { Create = 1 << 0, Read = 1 << 1, Update = 1 << 2, Delete = 1 << 3, // Limited to 60 'Things' ThingA = 1 << 4, ThingB = 1 << 5 } // User Model [Table(Name="Users")] public class User { [Column(IsPrimaryKey = true)] public string FName { get; set; } [Column] public Permissions Permissions { get; set; } public User() { } } 

ScenarioB:

 // // Scenario B: This would work too, but each new 'Thing' would need its own flag enum list stored in its own table (ThingXPermissions), // with another table linking ThingXPermissions.X to Users.ID (UserThingXPermissions) (yuck!) // Would like to avoid having to change database structure when adding more 'Things' in future. // User Model [Table(Name="Users")] public class User { [Column(IsPrimaryKey = true, IsDbGenerated = true)] public int ID { get; set; } private EntitySet<ThingAPermissions> userThingAPermissions = new EntitySet<ThingAPermissions>(); [Association(Name = "FK_User_UserThingAPermissions", Storage = "userThingAPermissions", OtherKey = "FK_User_Id", ThisKey = "ID")] public IEnumerable<ThingAPermissions> UserThingAPermissions { get { return userThingAPermissions; } } public IEnumerable<ThingAPermissions> ThingAPermissions { get { return (from up in UserThingAPermissions select up.UserThingAPermissions).AsEnumerable(); } } public User() { } } [Table(Name="UserThingAPermissions")] public class UserThingAPermissions { [Column(IsPrimaryKey = true)] public int FK_User_Id; private EntityRef<User> user; [Association(IsForeignKey = true, ThisKey = "FK_User_Id")] public User User { get { return user.Entity; } set { user.Entity = value; } } [Column] public ThingAPermissions ThingAPermissions { get; set; } } // ThingAPermissions [Flags] public enum ThingAPermissions : ulong { Create = 1 << 0, Read = 1 << 1, Update = 1 << 2, Delete = 1 << 3 } 

Desired scenario:

 // // Desired Scenario: Psuedo code of what I'd like to be able to do: // Single Permissions (CRUD) list // Single||simple Things list // Single||simple table associating UserX, ThingX, PermissionX // Example usage: // User Bob = new User(); // var desiredPermissions = Permissions.Create | Things.ThingZ; // Permission = Unique binary value combination of flags // if ((Bob.Permissions & desiredPermissions) == desiredPermissions) { // Bob has permission to Create ThingZ // Missing link: Combining enums and storing into database linked to user // eg // [Table = "UserPermissions"] // (User, Thing, Permission) // 1, ThingZ, Create // 1, ThingZ, Delete // 1, ThingX, Read // 2, ThingZ, Read // 2, ThingX, Delete [Flags] public enum Permissions : ulong { Create = 1 << 0, Read = 1 << 1, Update = 1 << 2, Delete = 1 << 3 } [Flags] public enum Things : ulong { ThingZ = 1 << 0, ThingY = 1 << 1, ThingX = 1 << 2, ThingW = 1 << 3 } [Table(Name="UserPermissions")] public class UserPermission { [Column(IsPrimaryKey = true)] public int FK_User_Id; private EntityRef<User> user; [Association(IsForeignKey = true, ThisKey = "FK_User_Id")] public User User { get { return user.Entity; } set { user.Entity = value; } } [Column] public int FK_Thing_Thing { get; set; } private EntityRef<Things> thing; [Association(IsForeignKey = true, ThisKey = "FK_User_Id")] public User User { get { return user.Entity; } set { user.Entity = value; } } [Column] public Permissions Permission { get; set; } } 

Additional code attempts:

Allow WPF-based authorization using the Enum checkbox

+6
source share
1 answer

Not sure if you fully understand how flags work. The reason you use the left shift operator, so your listings will be exponentials of the next value.

The flag attribute should tell .NET that the value of your enum can be a multiple.

For example, if you take ThingA and ThingB and add them (48)

Console.Write((Permissions)48));

The return value is BOTH ThingA and ThingB. You can just save it as a single ulong in the database, your code can figure out the rest.

+3
source

Source: https://habr.com/ru/post/952374/


All Articles