0

次のようにOrganizationクラスとUserクラスがあり、AddressUserとAddressOrganization、AddressAnythingなどの2つの個別の多対多テーブルを必要とせずに、それぞれに個別にアドレスを割り当てられるようにしたいと考えています。理由アドレスを割り当てたい複数のエンティティがあり、アドレスレコードを必要とするすべてのエンティティに中間結合テーブルが必要ない場合があります。

また、アドレスを関連付ける必要があるエンティティごとに、Address.OrganizationIdやAddress.UserIdなどの外部キーを保存したくありません。

Fluent APIまたはコードファーストデータアノテーションが、オブジェクトタイプを持つある種の複合ジェネリック外部キーに対応できる方法はありますか?

DomainObjectTypeテーブルのように?

DomainObjectType:

public class DomainObjectType
{
    [Key]
    public int Id { get; set; } // seeded

    public string ObjectType { get; set; } // User or Organization
}

DomainObjectTypeには、次のものがシードされます。

var objTypes = new List<DomainObjectType>
  { 
      new DomainObjectType() { Id = 1, ObjectType = "User" },
      new DomainObjectType() { Id = 2, ObjectType = "Organization" }
  };
objTypes.ForEach(c => context.DomainObjectTypes.Add(c));
context.SaveChanges();

組織:

public class Organization
    {    
        // Primary key
        [Key]
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }

        #region Navigation Properties

        public virtual ICollection<User> Users { get; set; }
        public virtual ICollection<Address> Addresses { get; set; }

        #endregion

    }

ユーザー

public class User
{
    [Key]
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int OrganizationId { get; set; }

    [ForeignKey("OrganizationId")]
    public virtual Organization Organization { get; set; }
    public virtual ICollection<Address> Addresses { get; set; }
}

住所

public class Address
{
    // Primary Key
    public int Id { get; set; }
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
    public string AddressType { get; set; }

    #region Foreign Keys

    // not completely sure about this? (maybe move to many-to-many "join" table)
    public int DomainObjectId { get; set; } // Composite key; would be either an OrganizationId or UserId
    public string DomainObjectTypeId { get; set; } // Composite key

    #endregion

    #region Navigation Properties

    public virtual ICollection<Organization> Organizations { get; set; }
    public virtual ICollection<User> Users { get; set; }

    #endregion

}

流暢なAPIのもの:

protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        // Configure Code First to ignore PluralizingTableName convention
        // If you keep this convention then the generated tables will have pluralized names.
        modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();

        // one-to-many Organization-to-Users
        modelBuilder.Entity<User>()
            .HasRequired(u => u.Organization)
            .WithMany(o => o.Users)
            .HasForeignKey(u => u.OrganizationId);

        // what goes here for generic AddressDomainObjectType?
    }
4

1 に答える 1

1

Addressたとえば、「他のエンティティ」の基本クラスを作成することで、「他のエンティティ」との間に多対多のテーブルを1つだけ持つという目的を達成できます。

public abstract class DomainObjectWithAddresses
{
    public int Id { get; set; }

    public virtual ICollection<Address> Addresses { get; set; }
}

public class User : DomainObjectWithAddresses
{
    // other properties but without Id which is inherited from base class
}

public class Organization : DomainObjectWithAddresses
{    
    // other properties but without Id which is inherited from base class
}

public class Address
{
    public int Id { get; set; }
    // other properties

    public virtual ICollection<DomainObjectWithAddresses> DomainObjects
                                                                 { get; set; }
}

Fluent APIを使用したマッピング:

modelBuilder.Entity<DomainObjectWithAddresses>()
    .HasMany(d => d.Addresses)
    .WithMany(a => a.DomainObjects)
    .Map(x =>
    {
        x.ToTable("DomainObjectAddresses");
        x.MapLeftKey("DomainObjectId");
        x.MapRightKey("AddressId");
    });

modelBuilder.Entity<User>()
    .ToTable("Users");           // TPT inheritance mapping

modelBuilder.Entity<Organization>()
    .ToTable("Organizations");   // TPT inheritance mapping

あなたDbContextDbSet基本タイプのために持っています:

public DbSet<DomainObjectWithAddresses> DomainObjects { get; set; }

私はそれが気に入りません。アドレスと多対多の関係を持つすべてのタイプに複数の結合テーブルを導入したいと思います。データベースにいくつかのテーブルを保存するためだけに、ドメインモデルに抽象化を導入するのは良い考えではないかと思います。この抽象DomainObjectWithAddressesクラスは非常に技術的な(「table-savings-helper」)アーティファクトであり、ドメインモデルでは価値のある意味を持ちません。私にとって、ユーザーはアドレスを持つオブジェクトであり、組織はアドレスを持つオブジェクトであると言うよりも、ユーザーにはアドレスがあり、組織にはアドレスがあると言う方がはるかに自然に聞こえます。長期的には、これはモデルの操作を複雑にするだけです。

于 2012-05-02T21:49:40.857 に答える