C# 将标志拆分为规范化表

C# 将标志拆分为规范化表,c#,linq,linq-to-entities,linqpad,C#,Linq,Linq To Entities,Linqpad,我有一张看起来像的桌子 OldThing id | Value | Flags | ... int | varchar | int | ... ... | ... | 2 | ... ... | ... | 19 | ... ... | ... | 82 | ... ... | ... | 3 | ... ... | ... | 19 | ... ... | ... | 3 | .

我有一张看起来像的桌子

OldThing
id  | Value    | Flags | ...
int | varchar  | int   | ...
... | ...      |   2   | ...
... | ...      |  19   | ...
... | ...      |  82   | ...
... | ...      |   3   | ...
... | ...      |  19   | ...
... | ...      |   3   | ...
... | ...      |  18   | ...
... | ...      |   3   | ...
... | ...      |  55   | ...
... | ...      |   3   | ...
... | ...      |  16   | ...
... | ...      |  16   | ...
... | ...      |  16   | ...
... | ...      |  16   | ...
... | ...      |  16   | ...
... | ...      |  16   | ...
... | ...      | 112   | ...
... | ...      |   3   | ...
... | ...      |   3   | ...
... | ...      |   3   | ...
... | ...      |  48   | ...
... | ...      |  16   | ...
... | ...      |  16   | ...
... | ...      |  64   | ...
... | ...      |  -1   | ...
... | ...      |   3   | ...
其中,
OldThing.Flags
在应用程序中被检查并生成为应用程序中定义的按位常量值

我正在尝试使用以下三个表来改进、更规范化的数据库:

Thing
id  | Value   | ...
int | varchar |

FlagDetail        
id  | description | mask
int | varchar     | int

Flag
ThingID | FlagID 
int     | int
我尝试使用带有自定义
IEqualityComparer
Join
生成FlagDetail表的值,但它返回的结果很少:

void Main()
{
    var flags = OldThings
           .ToArray()
           .Join(FlagDetails, thing=>thing.Flags.Value, 
                flag => flag.Mask, (t,f) => new {t, f}, 
                new BitwiseComparer())
           .Select (r => new Flag{ThingID = r.t.Id, FlagId = r.f.Id});

    Flags.InsertOnSubmit(flags);
    SubmitChanges();
}

// Define other methods and classes here
class BitwiseComparer : IEqualityComparer<int>
{
    public bool Equals(int a, int b)
    {
        return (a&b)>0;
    }

    public int GetHashCode(int n)
    {
        return 0;
    }
}
这些表在多个应用程序中使用,因此迁移将是渐进的,同时添加额外的
flagdail

是否有一种方法可以在Linq中生成
标志
值,而不必手动写入循环?我想要的东西可以在迁移每个应用程序时在LinqPad中快速轻松地输入和运行


我目前有
FlagDetail
行,其掩码值为
1
2
4

,除非我误解了,否则您需要做的是交叉连接,而不是正常连接

像这样,

var flags = from o in OldThings.ToArray()
            from f in FlagDetails
            where (o.Flags.Value & flag.Mask) > 0
            select new Flag{ThingID = o.Id, FlagId = f.Id};
假设您在
旧事物中有3行

1,'blah1',1
2,'blah2',2
3,'blah3',3

标记详细信息中的2行

1,'mask1',1
2,'mask2',2

您的加入将为您提供这一点,
标志

1,1
2,2
3,1

有了我的问题,你就有了

1,1
2,2
3,1
3,2


我不确定我是否理解你,但是。。。是否要将
oldsthings
FlagDetails
合并?我说得对吗?您尝试了什么?我正在尝试使用
flagdail.Mask
的值为
Flag
表生成行,因此在
(OldThing.Flags&flagdail.Mask)>0
时生成
Flag
行。我只是想知道在Linq中是否有一种方法可以做到这一点,但我没有。@MaciejLos经过编辑以包含以前的尝试。您能给我们提供OldThings flags列内容和new flag mask列内容吗?不需要身份证或身份证text@Fredou被编辑以包括的数量。
var flags = from o in OldThings.ToArray()
            from f in FlagDetails
            where (o.Flags.Value & flag.Mask) > 0
            select new Flag{ThingID = o.Id, FlagId = f.Id};