我正在使用Entity Framework 6 Code First将大型POCO模型存储在数据库中。该模型碰巧有1000个属性(不要问lol **),这意味着它必须拆分成多个SQL表(列限制为1024)。我知道这通常是通过指定各个列来完成的:
modelBuilder.Entity<HugeEntity>.Map(m =>
{
m.Properties(e => new { e.Prop1, e.Prop2 });
m.ToTable("HugeEntity1");
}.Map(m =>
{
m.Properties(e => new { e.Prop3, e.Prop4 });
m.ToTable("HugeEntity2");
};
我想知道是否有办法在不必单独指定属性的情况下执行此操作。理想情况下,它可以根据给定的列限制(即1000)自动对实体进行分区。
即使没有标准方法,最简单的方法是什么?模型上的属性可能会发生变化,因此我真的希望避免在不止一个地方详尽地列出它们。
任何建议表示赞赏!
** CONTEXT:这是一个域模型,表示用户输入的数据应该在某个网页上捕获。它也在WebAPI中公开。我的团队考虑了一种键/值对方法,但决定这会使未来的BI应用程序更难以使用WebAPI。
答案 0 :(得分:3)
你对我们说“不要问”。但你最大的问题是你自己说的。如果你的模型有超过50个字段,那么你需要询问发生了什么。我想知道是否值得深呼吸并重新审视一些更抽象的计算概念。我会从Database Normalization开始。 1K动态属性告诉我你迫切需要这个。
顺便说一句,“数据库规范化”概念本身并不特定于SQL数据库。您应该尽可能地将POCO模型标准化。当然,OO语言中存在一些非关系概念。但没有理由你所描述的极端。
另一种范例可能是Domain Driven Design。我自己不太流利,所以这就是为什么我不是说你应该从那里开始。但是从一开始我就实施它,我会说学习曲线是值得的。
我应该小心不要屈尊俯就。我自己并没有把所有表格都放在最高级的表格中。但我会告诉你,在我没有的地方,头痛更强烈。
答案 1 :(得分:1)
想出办法。我不得不使用Linq表达式和“动态”关键字:
private static void SplitIntoTables<T>(DbModelBuilder modelBuilder, IReadOnlyCollection<PropertyInfo> properties, int columnLimit) where T : class
{
var numberOfTables = Math.Ceiling((properties.Count + (double)columnLimit / 2) / columnLimit);
var paramExp = Expression.Parameter(typeof(T));
var tableIndex = 0;
foreach (var tableGroup in properties.GroupBy(p => p.Name.GetHashCode() % numberOfTables))
{
var expressions = tableGroup.Select(p => Expression.Lambda(
typeof(Func<,>).MakeGenericType(typeof(T), p.PropertyType),
Expression.Property(paramExp, p), paramExp));
modelBuilder.Entity<T>().Map(m =>
{
foreach (var exp in expressions)
{
m.Property((dynamic) exp);
}
m.ToTable($"{typeof(T).Name}_{++tableIndex}");
});
}
}