1

私は最初にEntityFrameworkコードを初めて使用するので、助けや指示をいただければ幸いです。

現在、次のクラスがあります。

public partial class Customer
{
    public int Id { get; set; }
    private ICollection<Address> _addresses;
}

public partial class Address
{
    public int Id { get; set; }
    public string Street { get; set; };
    public string City { get; set; };
    public string Zip { get; set; };
}

および以下

public partial class CustomerMap : EntityTypeConfiguration<Customer>
{
    public CustomerMap()
    {
        this.ToTable("Customer");
        this.HasKey(c => c.Id);

        this.HasMany<Address>(c => c.Addresses)
            .WithMany()
            .Map(m => m.ToTable("CustomerAddresses"));
    }
}

これは私が期待するとおりに機能し、マッピング用のCustomer、Address、およびCustomerAddressesテーブルを作成します。今私の質問のために..次を生成するためにコードを変更する必要がある場合はどうすればよいですか...

CompanyCode属性を"CustomerAddresses"テーブルに追加したい...そしてアドレスのコレクションを作成する代わりに..キーがCompanyCodeで、値がコレクションであるハッシュテーブルを作成できるようにしたいアドレスの。

したがって、次の場合:

Customer
ID     C1

Address
ID     A1
ID     A2

CustomerAddresses
CustomerID      C1
AddressID     A1
CompanyCode    ABC

CustomerID      C1
AddressID     A2
CompanyCode    ABC

CustomerID      C1
AddressID     A2
CompanyCode    XYZ

したがって、Customer.Addresses ["ABC"]は、ID、A1、およびA2のアドレスのコレクションを返します。一方、Customer.Addresses ["XYZ"]は、IDA2のアドレスのコレクションを返します。

どんな方向性/助けも大歓迎です...ありがとう。

4

1 に答える 1

1

私の知る限り、このようなナビゲーションプロパティをインデクサーで導入することはできません。インデクサーは実際にはクエリであり、これをクエリとして表現する必要があります。私が見る唯一の方法は、ナビゲーションコレクションをそのままにして、フィルターにナビゲーションコレクションを使用する2番目の(マップされていない)プロパティを導入することです。大きな欠点は、このようなフィルターがLINQ-to-Objectsを使用してメモリ内で発生し、コレクションをフィルター処理する前に、常にデータベースからコレクション全体を最初にロードする必要があることです(たとえば、積極的または遅延ロードによって)。

私はおそらく、そのようなフィルターをエンティティ自体から除外し、リポジトリまたはサービスクラス、または一般的にデータベースからエンティティをロードする場所/モジュールに実装します。

最初に行う必要があるのは、モデル内のエンティティとしてテーブルを公開することです。CustomerAddressesこれは、追加のカスタムプロパティCompanyCodeを使用すると、多対多の関係を使用できなくなり、代わりに2つの1対多の関係が必要になるためです。新しいエンティティは次のようになります。

public partial class CustomerAddress
{
    public int CustomerId { get; set; }
    // public Customer Customer { get; set; } // optional

    public int AddressId { get; set; }
    public Address Address { get; set; }

    public string CompanyCode { get; set; }
}

そして、次のCustomerように変更する必要があります。

public partial class Customer
{
    public int Id { get; set; }
    public ICollection<CustomerAddress> CustomerAddresses { get; set; }
}

マッピングを次のように変更する必要があります。

public CustomerMap()
{
    this.ToTable("Customer");
    this.HasKey(c => c.Id);

    this.HasMany(c => c.CustomerAddresses)
        .WithRequired() // or .WithRequired(ca => ca.Customer)
        .HasForeignKey(ca => ca.CustomerId);
}

そして、新しいエンティティの新しいマッピングを作成します。

public CustomerAddressMap()
{
    this.ToTable("CustomerAddresses");
    this.HasKey(ca => new { ca.CustomerId, ca.AddressId, ca.CompanyCode });
    // or what is the PK on that table?
    // Maybe you need an Id property if this key isn't unique

    this.HasRequired(ca => ca.Address)
        .WithMany()
        .HasForeignKey(ca => ca.AddressId);
}

これで、一部のサービスクラスで、フィルタリングされたアドレスをロードできます。

public List<Address> GetAddresses(int customerId, string companyCode)
{
    return context.CustomerAddresses.Where(ca =>
        ca.CustomerId == customerId && ca.CompanyCode == companyCode)
        .ToList();
}

または、フィルタリングされたアドレスと一緒に顧客をロードする場合:

public Customer GetCustomer(int customerId, string companyCode)
{
    var customer = context.Customer.SingleOrDefault(c => c.Id == customerId);
    if (customer != null)
        context.Entry(customer).Collection(c => c.CustomerAddresses).Query()
            .Where(ca => ca.CompanyCode == companyCode)
            .Load();
    return customer;
}

最後の例は、2つのデータベースクエリです。

エンティティでは、コレクションCustomerからアドレスを投影するヘルパープロパティを使用できます。CustomerAddresses

public partial class Customer
{
    public int Id { get; set; }
    public ICollection<CustomerAddress> CustomerAddresses { get; set; }

    public IEnumerable<Address> Addresses
    {
        get
        {
            if (CustomerAddresses != null)
                return CustomerAddresses.Select(ca => ca.Address);
            return null;
        }
    }
}

このプロパティはデータベースをクエリせず、結果はにすでにロードされているものに依存することに注意してCustomerAddressesください。

于 2012-10-03T14:15:44.987 に答える