2013-08-23 3 views
6

इस प्रश्न का पहला जवाब: What to do when bit mask (flags) enum gets too large ठीक है जो मैं करने की कोशिश कर रहा हूं, केवल मुझे नहीं पता कि डेटाबेस में इसे कैसे स्टोर किया जाए LINQ से SQL और प्रत्येक चीज़/लॉजिकल समूह के लिए 2 टेबल बनाने के बिना उपयोगकर्ताओं को टाई।बिटकमास्क (झंडे) एनम 64 से परे बिटरैरे के साथ डेटाबेस में संग्रहीत लॉजिकल ग्रुपिंग के साथ

यह सबसे अच्छा कोड के माध्यम से समझाया गया है (इन हालांकि अधूरा अनुकूल LINQPad हैं):

// 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 
} 

वांछित परिदृश्य:

// 
// 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; } 
} 

अतिरिक्त कोड का प्रयास:

WPF permission-based authorization using Enum Flag Bit

+0

मुझे नहीं लगता कि आपको प्रत्येक लॉजिकल समूह के लिए दो टेबल की आवश्यकता होगी। यदि आपने अपने enums के लिए बिटमैस्किंग का उपयोग किया था और एक और चीज़ 1/thing2/thing3 में किसी अन्य में बना/हटा/अपडेट किया था तो आप एनम पर फिर से सक्रिय हो सकते हैं और उपयोगकर्ता के लिए प्रत्येक लॉजिकल जोड़ी के लिए डीबी में एक पंक्ति स्टोर कर सकते हैं, आप भी केवल लॉजिकल जोड़े को स्टोर करें जो उपयोगकर्ता पर लागू होते हैं, इसलिए अधिकतम चार पंक्तियां अधिकतम होती हैं। बनाएँ/अपडेट/हटाएं/पढ़ें (प्रत्येक अपनी पंक्ति में) के लिए एक कॉलम और दूसरा कॉलम जो चीज़ 1/thing2/thing3 का बिटमैस्क था। मुझे नहीं लगता कि चार कॉलम बहुत अधिक अतिरिक्त हैं ... - हालांकि मुझे कुछ याद आ रहा है ... :) – Faraday

उत्तर

3

सुनिश्चित नहीं है कि आप पूरी तरह से समझते हैं कि झंडे कैसे काम करते हैं। बाएं शिफ्ट ऑपरेटर का उपयोग करने का कारण यह है कि आपके enums निम्न मान के घाटेदार होंगे।

ध्वज विशेषता है .NET को पता है कि आपके enum का मान गुणक हो सकता है।

उदाहरण के लिए यदि आप अपने thinga और ThingB लेते हैं और उन्हें (48)

Console.Write((Permissions)48));

दिए गए मान दोनों thinga और ThingB है जोड़ें। आप डेटाबेस में इसे एक ulong के रूप में सहेजने में सक्षम होंगे, आपका कोड बाकी को समझने में सक्षम होगा।

संबंधित मुद्दे