将标志拆分为标准化 Table
Split Flags into Normalized Table
我有一个 table 看起来像
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
在应用程序中被检查并生成为按位和应用程序中定义的常量值。
我正在尝试使用以下三个 tables:
改进、更规范化的数据库
Thing
id | Value | ...
int | varchar |
FlagDetail
id | description | mask
int | varchar | int
Flag
ThingID | FlagID
int | int
我尝试使用 Join
和自定义 IEqualityComparer
生成 FlagDetail table 的值,但它返回的结果很少是我想要的:
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;
}
}
这产生了 19 个结果,而预期的行数应该是 29(由 SubscriptionTypes.Sum(st => EmailNames.Count(n => (n.Subscriptions & st.Mask)>0));
计算)。
最后,我使用了两个嵌套的 foreach
循环:
var flags = new List<Flag>();
foreach (var thing in OldThings)
{
foreach (var flag in FlagDetails)
{
if ((thing.Flag & flag.Mask) > 0)
subs.Add(new Flag{ThingId = Thing.Id, FlagId = flag.Id});
}
}
Flags.InsertAllOnSubmit(flags);
SubmitChanges();
这些 table 在多个应用程序中使用,因此迁移将逐步添加额外的 FlagDetail
行。
有没有办法在 Linq 中生成 flags
值,而无需手动编写循环?我正在寻找可以在迁移每个应用程序时在 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};
假设您在 OldThings
;
中有 3 行
1, 'blah1', 1
2, 'blah2', 2
3, 'blah3', 3
和 FlagDetails
中的 2 行;
1, 'mask1', 1
2, 'mask2', 2
你的加入会给你这个,Flag
;
1, 1
2, 2
3, 1
通过我的查询,您将得到
1, 1
2, 2
3, 1
3, 2
我有一个 table 看起来像
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
在应用程序中被检查并生成为按位和应用程序中定义的常量值。
我正在尝试使用以下三个 tables:
改进、更规范化的数据库Thing
id | Value | ...
int | varchar |
FlagDetail
id | description | mask
int | varchar | int
Flag
ThingID | FlagID
int | int
我尝试使用 Join
和自定义 IEqualityComparer
生成 FlagDetail table 的值,但它返回的结果很少是我想要的:
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;
}
}
这产生了 19 个结果,而预期的行数应该是 29(由 SubscriptionTypes.Sum(st => EmailNames.Count(n => (n.Subscriptions & st.Mask)>0));
计算)。
最后,我使用了两个嵌套的 foreach
循环:
var flags = new List<Flag>();
foreach (var thing in OldThings)
{
foreach (var flag in FlagDetails)
{
if ((thing.Flag & flag.Mask) > 0)
subs.Add(new Flag{ThingId = Thing.Id, FlagId = flag.Id});
}
}
Flags.InsertAllOnSubmit(flags);
SubmitChanges();
这些 table 在多个应用程序中使用,因此迁移将逐步添加额外的 FlagDetail
行。
有没有办法在 Linq 中生成 flags
值,而无需手动编写循环?我正在寻找可以在迁移每个应用程序时在 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};
假设您在 OldThings
;
1, 'blah1', 1
2, 'blah2', 2
3, 'blah3', 3
和 FlagDetails
中的 2 行;
1, 'mask1', 1
2, 'mask2', 2
你的加入会给你这个,Flag
;
1, 1
2, 2
3, 1
通过我的查询,您将得到
1, 1
2, 2
3, 1
3, 2