La prima risposta a questa domanda: What to do when bit mask (flags) enum gets too large è esattamente ciò che sto cercando di fare, solo che non so come memorizzarlo nel database usando LINQ to SQL e legalo agli utenti senza creare 2 tabelle per ogni cosa/gruppo logico.Bitmask (flag) enumerazione oltre 64 con bitarray con raggruppamento logico memorizzato nel database
Questo si spiega meglio tramite codice (questi sono LINQPad cordiale anche se incompleto):
// Requirements:
// 1) Using LINQ to SQL
// 2) Track User's 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
}
scenario desiderato:
//
// 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
// e.g.
// [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; }
}
Ulteriori tentativi di codice:
WPF permission-based authorization using Enum Flag Bit
Non penso che avresti bisogno di due tabelle per ogni gruppo logico. Se hai usato la maschera dei bit per l'enumerazione e hai creato/elimina/aggiorna in uno e cosa1/cosa2/cosa3 in un altro, puoi semplicemente ripetere l'enumerazione e memorizzare una riga nel DB per ciascuna coppia logica per l'utente, inoltre memorizza solo le coppie logiche che si applicano all'utente, quindi come quattro righe max. Una colonna per Crea/Aggiorna/Elimina/Leggi (ciascuna nella propria riga) e una seconda colonna che era una maschera di bit di thing1/thing2/thing3. Non credo che quattro colonne siano troppo extra ... - Potrei mancare qualcosa però ... :) – Faraday