3

私は多対1の関係を確立しようとしています。「多く」を表すエンティティには、親エンティティを指すナビゲーションプロパティがあります。次のようになります。

public abstract class BaseEntity
{

    /// <summary>
    /// Key Field for all entities
    /// </summary>
    /// 
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public Guid Id { get; set; }


    /// <summary>
    /// Date entity was created
    /// </summary>
    public DateTime DateCreated { get; set; }

    /// <summary>
    /// Last date Modified
    /// </summary>
    public DateTime DateModified { get; set; }

    /// <summary>
    /// keep track of Row Version used for concurrency
    /// </summary>
    [Timestamp]
    public Byte[] RowVersion { get; set; }

}

public abstract class Document : BaseEntity
{
    #region Primitive Properties   


    /// <summary>
    /// Boolean value to determine if Document is in an active state
    /// </summary>
    public bool IsActive { get; set; }

    /// <summary>
    /// Document comments and information
    /// </summary>
    [Required]
    public string Description { get; set; }

    #endregion

    #region Navigation Properties

    public ICollection<Comment> Comments { get; set; }

    /// <summary>
    /// FK back to User who owns document
    /// </summary>
    //public Guid OwnerId { get; set; }

    public Guid OwnerId { get; set; }
    /// <summary>
    /// Navigation Back to User who owns document
    /// </summary>
    public User Owner { get; set; }

    #endregion
}

public class Project : BaseEntity
{
    public string Name { get; set; }
    public string ProjectNumber { get; set; }
    public string Description { get; set; }

    public string CreatedBy { get; set; }
    public string ModifiedBy { get; set; }
    public string Currency { get; set; }

    #region Navigation Properties

    public virtual Address Address { get; set; }
    public virtual CompanyCode CompanyCode { get; set; }
    public virtual ICollection<Contact> TeamMembers { get; set; }

    #endregion
}    

 public class Rfi : Document
 {
    public string Number { get; set; }

    #region Navigation Properties

    //This points back to a Project Entity
    public virtual Guid ProjectId { get; set; }
    public virtual Project Project { get; set; }

    #endregion
}

したがって、上記のエンティティを挿入すると、ProjectIdがアプリケーションからRfiエンティティ(Projectエンティティ全体ではなく)に渡されます。すべてがうまく保存されます。私が抱えている問題は、Rfiオブジェクトをデータベースからプルバックすると、ProjectIdが入力されていますが、Projectエンティティがnullであるということです。デフォルトでは、遅延読み込みを使用しています。Projectエンティティにもナビゲーションプロパティを指定する必要がありますか?私は本当にしたくありません。そうでない限り、これを達成するためにRfiでマッピングを実行できます。

更新:EF 4.1でオブジェクトが読み込まれると想定しましたが、読み込みたいオブジェクトを明示的に含める必要がある場合があります。理由はよくわかりません。リポジトリを使用してエンティティをクエリしています。Rfiオブジェクトのクエリに使用したメソッドは次のとおりです。

    public IQueryable<TEntity> GetQuery(Expression<Func<TEntity, bool>> predicate)
    {
       return _context.Set<TEntity>().AsQueryable();
    }

私がやったことは、私のサービスレイヤーでは次のように呼んでいます。

public Rfi FindByNumber(string number)
{
     var rfi = rfiRepository.GetQuery(r => r.Number == number).Include(r => r.Project).Single;
     return rfi
}
4

2 に答える 2

13

virtual遅延読み込みを機能させるには、ナビゲーションプロパティを作成する必要があります。

これは実装に関しては理にかなっていますが、問題を無視してただ戻るというEFの戦略nullは、ひどい設計上の決定です。

一方、NHibernateでは、デフォルトでは、すべてのプロパティが仮想化されていないクラスを使用できません。

この問題を回避するために、すべての参照プロパティが仮想としてマークされていることを確認するテストを作成しました。そうすれば、将来の奇妙なバグに対処する代わりに、すぐに見つけることができます。


FK/Navigationプロパティを明示的に指定することもできます。

public Guid ProjectId { get; set; }
[ForeignKey("ProjectId")]
public virtual Project Project { get; set; }
于 2011-05-27T12:34:58.620 に答える
3

プロパティ用に作成したマッピングは、データベースに重複したIDを作成していたことがわかりました。たとえば、データベースにProjectIdありました。新しいアイテムがコンテキストに保存されたときに入力していましたが、入力されていませんProject_IDでした。これは、EF4.1がデータを関連付けるために使用しているものです。私のマッピングでは、プロジェクトを設定しないように設定していました。これは私のマッピングがどのように見えるかです:ProjectId_IDCascadeOnDelete

HasOptional(rfi => rfi.Project)
    .WithOptionalDependent()
    .WillCascadeOnDelete(false);

このマッピングは、データベースに2つのIDを作成していました。マッピングを削除すると、すべてが機能していました。を削除しCascadeOnDelete、プロパティをオプションにし、IDを1つだけ持つことができるように、正しいマッピングを理解する必要があります。

私はEFパワーツールの助けを借りて理解した。DBをPOCOにリバースエンジニアリングできます。上記の行を次のように変更しました。

HasOptional(r => r.Project)
    .WithMany()
    .HasForeignKey(r => r.ProjectId)
    .WillCascadeOnDelete(false);

流暢なインターフェースでも、マッピングをマスターするのは少し難しいです。EFで関係がどのようにマッピングされるかを理解するために、テーブルと外部キーの割り当てを使用して単純なデータベースを作成しました。次に、最初にコードをリバースエンジニアリングするためにPowerToolsのオプションを使用しました。素晴らしい!

于 2011-06-23T13:27:02.277 に答える