0

Complex Typeクラスの実装をリファクタリングして、不変型にするバリューオブジェクトパターンを適用しました。バリューオブジェクトパターンにリファクタリングした後、EFCF 6の複合型マッピングに失敗しました

これらの変更のための移行をセットアップしようとするまで、私は考えていました(私がEFにとって重要な主な変更は、いくつかのプロパティを変更したことですセッターを持っていた)。私は更新-データベースを実行したとき、私は現在、次のエラーを取得しています:

PM> update-database 
Specify the '-Verbose' flag to view the SQL statements being applied to the target database. 
Applying explicit migrations: [201701010745393_initial]. 
Applying explicit migration: 201701010745393_initial. 
Running Seed method. 
System.Data.Entity.Core.EntityCommandCompilationException: An error occurred while preparing the command definition. See the inner exception for details. ---> System.Data.Entity.Core.MappingException: 
(29,10) : error 3004: Problem in mapping fragments starting at line 29:No mapping specified for properties Contact.Address in Set Contacts. 

(46,10) : error 3004: Problem in mapping fragments starting at line 46:No mapping specified for properties Company.Address in Set Companies. 

(56,10) : error 3004: Problem in mapping fragments starting at line 56:No mapping specified for properties CompanyLocation.Address in Set Locations. 

これは私はEFの複合型をどのように処理するかについて読んでてきたものを挑むことに見える、それは実体に遭遇した時はいつでも、それは自動的に物事をマップする必要があるという点で、複合型のプロパティを使用します。これは以前のケースでしたが、変更不可能なクラスへの変更がなくなったのはです。私はそれがなぜであるか分かりません。

public class Company : PocoBase 
{ 
    [Required] 
    public Address Address { get; set; } 

    public virtual ICollection<Client> Clients { get; set; } 

    public virtual ICollection<CompanyLocation> Locations { get; set; } 

    [Required] 
    public string Name { get; set; } 
} 

public class CompanyLocation : PocoBase 
{ 
    [Required] 
    public Address Address { get; set; } 

    public virtual Company Company { get; set; } 

    [ForeignKey("Company")] 
    public Guid CompanyId { get; set; } 

    public string Description { get; set; } 

    public string Label { get; set; } 
} 

public class Contact : PocoBase 
{ 
    public Address Address { get; set; } 

    [Required] 
    public string CellNumber { get; set; } 

    public virtual Client Client { get; set; } 

    [ForeignKey("Client")] 
    public Guid ClientId { get; set; } 

    public virtual Company Company { get; set; } 

    [ForeignKey("Company")] 
    public Guid CompanyId { get; set; } 

    [Required] 
    public string Email { get; set; } 

    [Required] 
    public string Name { get; set; } 

    [Required] 
    public string OfficeNumber { get; set; } 
} 

そして、今、問題を引き起こしているもちろん、すべての重要なAddressクラス、:ここで

は、これらのエラーメッセージに関連する関連クラスです!私は、移行を追加実行するとEFを作成しようとしない、そのファイルが、これはしなかったの移行にAddress_PropertyName - 私はEFCF条約があると信じて同じ調子で、手動でこのマッピングを行うことを試みた

[ComplexType] 
public class Address 
{ 
    [Required] 
    public string City { get; } 

    [Required] 
    public string Country { get; } 

    [Required, StringLength(10, MinimumLength = 5)] 
    public string PostalCode { get; } 

    [Required, StringLength(2, MinimumLength = 2)] 
    public string State { get; } 

    [Required] 
    public string StreetAddress { get; } 

    public string UnitNumber { get; } 

    public Address(string street, string city, string state, string zip, string unit = null) : this("United States", street, city, state, zip, unit) { } 

    public Address(string country, string street, string city, string state, string zip, string unit = null) 
    { 
     VerifyZipCodeFormat(zip); 

     Country = country; 
     StreetAddress = street; 
     City = city; 
     State = state; 
     PostalCode = zip; 
     UnitNumber = unit; 
    } 

    private static void VerifyZipCodeFormat(string zip) 
    { 
     if (zip.Length > 5) 
      if (zip[5] != '-') 
       throw new ArgumentOutOfRangeException(nameof(zip), zip[5], "Postal Code must be in the format of \"XXXXX\" or \"XXXXX-XXXX\""); 
      else if (zip.Length != 10) 
       throw new ArgumentOutOfRangeException(nameof(zip), zip.Length, "Postal Code must be either 5 or 10 characters, in either the format of \"XXXXX\" or \"XXXXX-XXXX\""); 
    } 

    public Address WithCity(string city) 
    { 
     return new Address(Country, StreetAddress, city, State, PostalCode, UnitNumber); 
    } 
    public Address WithCountry(string country) 
    { 
     return new Address(country, StreetAddress, City, State, PostalCode, UnitNumber); 
    } 
    public Address WithStateOrProvince(string state) 
    { 
     return new Address(Country, StreetAddress, City, state, PostalCode, UnitNumber); 
    } 
    public Address WithStreetAddress(string street) 
    { 
     return new Address(Country, street, City, State, PostalCode, UnitNumber); 
    } 
    public Address WithUnitNumber(string unit) 
    { 
     return new Address(Country, StreetAddress, City, State, PostalCode, unit); 
    } 
    public Address WithZipOrPostalCode(string zip) 
    { 
     VerifyZipCodeFormat(zip); 

     return new Address(Country, StreetAddress, City, State, zip, UnitNumber); 
    } 
} 

いずれかの作業。

[ComplexTypeAttribute]を持たず、modelBuilder.ComplexType()行を使用してもこれらのエラーメッセージが解決されていないため、これは不変クラスであることに関連していると仮定する必要があります。

[ColumnAttribute]に列名を追加すると、何とか問題が解決されると期待していましたが、this postに示されているように見えますが、それでも問題は解決しませんでした。

答えて

2

どちらも有する[ComplexTypeAttribute]もmodelBuilder.ComplexTypeを()線は、これらのエラーメッセージを解決したので、私はそれが、これは今不変クラスであることに関係していると仮定しなければならない使用。

これは正しいです。 EF6はプロパティのみをマップしません。データ注釈や流暢な設定でその動作を変更する方法はありません(EF Coreの動作は異なりますが、still causes issues)ので、プライベートセッターを提供して問題を解決します。

[ComplexType] // optional 
public class Address 
{ 
    [Required] 
    public string City { get; private set; } 

    [Required] 
    public string Country { get; private set; } 

    [Required, StringLength(10, MinimumLength = 5)] 
    public string PostalCode { get; private set; } 

    [Required, StringLength(2, MinimumLength = 2)] 
    public string State { get; private set; } 

    [Required] 
    public string StreetAddress { get; private set; } 

    public string UnitNumber { get; private set; } 

    // ... 
} 

これは、フィールドが構築中にのみ設定されることを保証する元の実装と同等ではないことが分かりました。しかし、一般的には、EFエンティティをモデリングする際に、オブジェクト指向の原則、パターン、およびプラクティスを忘れてしまうことをお勧めします。エンティティクラスは基本的に、データベーステーブル、レコード、および関連するビジネスロジックがない関係を表すDTOです。また、EFは参照IDを使用してエンティティを追跡するので、エンティティタイプに不変の原則を適用するだけで問題が発生します(幸いにも複雑な型には適用されません)。

+0

この情報をお寄せいただきありがとうございます、Ivan。これがマイクロソフトによって明記されている場所を知っていますか?私は将来、このようなものをどこで見なければならないのか分かりません。この質問をする前に、Google検索はあまり役に立ちませんでした。 –

+1

こんにちはクリス、残念ながらいいえ。EF情報は、主にEFチームのブログ記事から収集されたり、試してみるだけです(試行錯誤、あなたも知っています)。 –

関連する問題