我有一张表格,看起来像这样:
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;
}
}
这导致了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();
这些表格被用于多个应用程序,因此迁移将是逐步的,并随着我们的迁移逐渐添加额外的
FlagDetail
行。有没有一种方法可以在 Linq 中生成
flags
值,而不必手动编写循环?我想要的是一些可以快速轻松地在 LinqPad 中输入并运行的东西,同时还要迁移每个应用程序。我目前有 Mask 值为
1
、2
和 4
的 FlagDetail
行。
OldThings
和FlagDetails
进行连接吗?我说得对吗?你尝试过什么? - Maciej Los