实体框架以编程方式将模型拆分为多个表

时间:2017-06-28 19:04:04

标签: c# sql-server entity-framework entity-framework-6

我正在使用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。

2 个答案:

答案 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}");
            });
        }
    }