使用fluent API在EF Core中创建模型时避免重复代码的最佳方法

时间:2019-12-16 15:21:45

标签: ef-core-3.0

我有一个值类型“ Address”,该值类型在我的模型中的几个地方使用,例如:Company.PostalAddress,Company.ShippingAddress和Employee.HomeAddress。

数据上下文类中的OnModelCreating方法将如下所示:

    protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.Entity<Company>(companyBuilder =>
        {
            companyBuilder.ToTable("Company");
            companyBuilder.HasKey(company => company.Id);

            companyBuilder.Property(company => company.Id).IsRequired().UseIdentityColumn();
            companyBuilder.Property(company => company.Name).IsRequired().HasMaxLength(100);

            companyBuilder.OwnsOne(company => company.PostalAddress, addressBuilder =>
            {
                addressBuilder.Property(address => address.Street).IsRequired().HasMaxLength(100);
                addressBuilder.Property(address => address.HouseNumber).IsRequired();
                addressBuilder.Property(address => address.HouseNumberExtension).HasMaxLength(20);
                addressBuilder.Property(address => address.ZipCode).IsRequired().HasMaxLength(10);
                addressBuilder.Property(address => address.City).IsRequired().HasMaxLength(50);
            });

            companyBuilder.OwnsOne(company => company.VisitingAddress, addressBuilder =>
            {
                addressBuilder.Property(address => address.Street).IsRequired().HasMaxLength(100);
                addressBuilder.Property(address => address.HouseNumber).IsRequired();
                addressBuilder.Property(address => address.HouseNumberExtension).HasMaxLength(20);
                addressBuilder.Property(address => address.ZipCode).IsRequired().HasMaxLength(10);
                addressBuilder.Property(address => address.City).IsRequired().HasMaxLength(50);
            });

            companyBuilder.OwnsOne(company => company.ShippingAddress, addressBuilder =>
            {
                addressBuilder.Property(address => address.Street).IsRequired().HasMaxLength(100);
                addressBuilder.Property(address => address.HouseNumber).IsRequired();
                addressBuilder.Property(address => address.HouseNumberExtension).HasMaxLength(20);
                addressBuilder.Property(address => address.ZipCode).IsRequired().HasMaxLength(10);
                addressBuilder.Property(address => address.City).IsRequired().HasMaxLength(50);
            });

            companyBuilder.HasIndex(company => company.Name).IsUnique();
        });

        builder.Entity<Employee>(employeebuilder =>
        {
            employeebuilder.ToTable("Employee");
            employeebuilder.HasKey(employee => employee.Id);

            employeebuilder.Property(employee => employee.Id).IsRequired().UseIdentityColumn();
            employeebuilder.Property(employee => employee.FirstName).IsRequired();

            employeebuilder.OwnsOne(employee => employee.HomeAddress, addressBuilder =>
            {
                addressBuilder.Property(address => address.Street).IsRequired().HasMaxLength(100);
                addressBuilder.Property(address => address.HouseNumber).IsRequired();
                addressBuilder.Property(address => address.HouseNumberExtension).HasMaxLength(20);
                addressBuilder.Property(address => address.ZipCode).IsRequired().HasMaxLength(10);
                addressBuilder.Property(address => address.City).IsRequired().HasMaxLength(50);
            });

        });
    }

这有很多代码重复,所以我创建了一个私有方法来将Address配置放在一个地方:

    private static void Build<T>(OwnedNavigationBuilder<T, Address> addressBuilder) where T : class
    {
        addressBuilder.Property(address => address.Street).IsRequired().HasMaxLength(100);
        addressBuilder.Property(address => address.HouseNumber).IsRequired();
        addressBuilder.Property(address => address.HouseNumberExtension).HasMaxLength(20);
        addressBuilder.Property(address => address.ZipCode).IsRequired().HasMaxLength(10);
        addressBuilder.Property(address => address.City).IsRequired().HasMaxLength(50);
    }

这允许我将OnModelCreating方法更改为此:

    protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.Entity<Company>(companyBuilder =>
        {
            companyBuilder.ToTable("Company");
            companyBuilder.HasKey(company => company.Id);

            companyBuilder.Property(company => company.Id).IsRequired().UseIdentityColumn();
            companyBuilder.Property(company => company.Name).IsRequired().HasMaxLength(100);

            companyBuilder.OwnsOne(company => company.PostalAddress, addressBuilder => Build(addressBuilder));

            companyBuilder.OwnsOne(company => company.VisitingAddress, addressBuilder => Build(addressBuilder));

            companyBuilder.OwnsOne(company => company.ShippingAddress, addressBuilder => Build(addressBuilder));

            companyBuilder.HasIndex(company => company.Name).IsUnique();
        });

        builder.Entity<Employee>(employeebuilder =>
        {
            employeebuilder.ToTable("Employee");
            employeebuilder.HasKey(employee => employee.Id);

            employeebuilder.Property(employee => employee.Id).IsRequired().UseIdentityColumn();
            employeebuilder.Property(employee => employee.FirstName).IsRequired();

            employeebuilder.OwnsOne(employee => employee.HomeAddress, addressBuilder => Build(addressBuilder));

        });
    }

但是,Microsoft声明OwnedNavigationBuilder类不能直接在代码中使用,因为它可能“在任何发行版本中未经通知即被更改或删除”。

所以我的问题是:如何避免在不直接调用EF Core内部类的情况下反复重复相同的配置?

0 个答案:

没有答案