2011-01-06 11 views
1

これを理解するのを手伝ってください。私はこれが重複した質問であることをお詫びしますが、私が仕事をするために読んでいる何かを得ることができないようです。NHibernate 3.0無効なインデックス例外が発生しました。プロパティを解決できませんでした:{foreign key property}

ASP.NET MVC 2を使用してWebサイトを構築するために、NHibernate 3.0、C#、.NET Framework 4.0およびSQL Server 2005を使用しています。 ここに状況があります。私は親子関係を持つ2つのテーブルを持っています。私はInvalid index N for this SqlParameterCollection with Count=N.の例外を受け取りました。

Derik Whittaker's post at http://devlicio.us/blogs/derik_whittaker/archive/2009/03/19/nhibernate-and-invalid-index-n-for-this-sqlparametercollection-with-count-n-error.aspxを読んだ後、私は子テーブルの外部キー列をプロパティにマップし、子クラスの親クラスオブジェクトをマップしていることに気付きました。だからDerikの投稿ごとに、hbm.xmlファイルのプロパティマッピングを外部キーに削除し、parentEntity.PrimaryKeyプロパティから値を取得するようにプロパティを設定しました。今度は、NHibernateが外部キーのプロパティを解決できないというエラーが表示されます。

ここで私は朝の狩りのほとんどを費やして以来、子フィールドに外部キーを保持し、外部キーへのマッピングに戻すプライベートフィールドを追加しました。access属性をfieldに設定しました。 。 NHibernateは依然として外部キーのプロパティにアクセスできません。他の投稿から収集された情報を使って、データベース内のすべてのnull可能な列がエンティティクラスのnull可能なプロパティに対応していることを確認しました。また、データベースに孤立した子がないことを確認しました。存在しないので、親エンティティオブジェクトにアクセスする際にnull参照を打つべきではありません。私はまた、Hibernateがデータベースから親を取得していないことが問題であると考えて、私の子エンティティマップで遅延ロードをオフにしてみました。それも問題ではありませんでした。

デバッガでコードをステップ実行すると、データモデルをビューモデルに投影しようとするとエラーが発生します。投影前に元のクエリに戻り、データベースから取得した値を調べると、外部キーのプロパティに値が設定されていることがわかります。孤児が孤立している場合、これを問題として見ることができましたが、前にも述べたように、そうではありません。残念ながら、私はlinqの選択クエリで投影を行っているので、私は個々の値を見ることができないので、私は今なぜ突然外来キーを見つけることができないのかわかりません!

残念ながら、この親子関係自体はデータベースには表現されていません。関係自体は私のコードで完全に表現されています。ここで

は、テーブルのrelevent構造である:

親テーブル:

CREATE TABLE [dbo].[POSErrorQueue](
[HeaderID] [int] IDENTITY(1,1) NOT NULL, 
    ---About 75 other parent table specific columns--- 
CONSTRAINT [PK_POSErrorQueue] PRIMARY KEY CLUSTERED 
(
[HeaderID] ASC 
) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

子テーブル:

CREATE TABLE [dbo].[POSErrorQueueDetails](
[DetailID] [int] IDENTITY(1,1) NOT NULL, 
[HeaderID] [int] NOT NULL, 
    ---About 20 other child table specific columns--- 
CONSTRAINT [PK_POSErrorQueueDetails] PRIMARY KEY CLUSTERED 
(
[DetailID] ASC 
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] 
) ON [PRIMARY] 

そして、ここではすべて行った後、私のコードでは、関連するクラスです上記の変更点:

親クラス:

public class POSErrorQueue 
{ 
    public virtual Int32 HeaderID {get; set;} 
    //all other table columns as properties 
    public virtual IEnumerable<POSErrorQueueDetail> Details { get; set; } 
} 

子供クラス:

public class POSErrorQueueViewModel 
{ 
    public int HeaderID { get; set; } 
    public int DetailID { get; set; } 
    public string DistributorID { get; set; } 
    public string BranchCustomerID { get; set; } 
    public string InvoiceID { get; set; } 
    public DateTime InvoiceDate { get; set; } 
    public string ProductDescription { get; set; } 
    public string DentsplyProductID { get; set; } 
    public string ProductSource { get; set; } 
    public string ErrorDescription { get; set; } 
    public decimal? Quantity { get; set; } 
    public decimal? UnitSalePrice { get; set; } 
    public decimal TotalLinePrice 
    { 
     get 
     { 
      if (Quantity.HasValue && UnitSalePrice.HasValue) 
      { 
       return Quantity.Value * UnitSalePrice.Value; 
      } 
      else 
      { 
       return 0; 
      } 
     } 
    } 
    public string OrderType { get; set; } 
} 
ここ

私のマッピングファイルは、次のとおりです:

public class POSErrorQueueDetail 
{ 
    private Int32 _headerId; 
    public virtual Int32 DetailID { get; set; } 
    public virtual Int32 HeaderID { get { return Header.HeaderID; } } 
    //all other table columns as properties 
    public virtual POSErrorQueue Header { get; set; } 
} 

私はこれは本当にreleventですが、ここに私のviewmodelクラスであるかどうかわからないんだけど

親地図:

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="TPMControlPanel" namespace ="TPMControlPanel.Models"> 
    <class name="POSErrorQueue" table="POSErrorQueue"> 
    <id name="HeaderID"> 
     <generator class="identity" /> 
    </id> 
    <!--all other property mappings removed for brevity --> 
    <set name="Details" inverse="true"> 
     <key column="HeaderID" /> 
     <one-to-many class="POSErrorQueueDetail"/> 
    </set> 
    </class> 
</hibernate-mapping> 

子マップ:省略さプロパティマッピングの

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="TPMControlPanel" namespace ="TPMControlPanel.Models"> 
    <class name="POSErrorQueueDetail" table="POSErrorQueueDetails"> 
    <id name="DetailID"> 
     <generator class="identity" /> 
    </id> 
    <property name="_headerId" column="HeaderID" access="field" /> 
    <!--all other property mappings removed for brevity --> 
    <many-to-one name="Header" class="POSErrorQueue" column="HeaderID" fetch="join" /> 
    </class> 
</hibernate-mapping> 

、プロパティの名前とテーブル内の関連する列は同一です。

そして最後に、ここで実際にエラーを生成するコードは次のとおりです。私は上記のコメントと同様

public IList<POSErrorQueueViewModel> GetFiltered(Models.FilterModels.POSErrorFilterFields filterFields, DateTime fromDate, DateTime toDate) 
    { 
     var query = MvcApplication.DENTSPLYSession.Query<POSErrorQueueDetail>().Where(d => d.InvoiceDate > fromDate && 
      d.InvoiceDate < toDate); 
     //About 20 lines of if statements used to filter the query removed for brevity. 
     var detailView = query.Select(e => new POSErrorQueueViewModel 
     { 
      HeaderID = e.HeaderID, 
      DetailID = e.DetailID, 
      BranchCustomerID = e.Header.BranchCustomerID, 
      DistributorID = e.Header.DistributorID, 
      DentsplyProductID = e.DentsplyProductID, 
      ErrorDescription = e.ErrorDescription, 
      InvoiceID = e.InvoiceID, 
      InvoiceDate = e.InvoiceDate.Value, 
      OrderType = e.OrderType, 
      ProductDescription = e.ProductDescription, 
      ProductSource = e.ProductSource, 
      Quantity = e.Quantity, 
      UnitSalePrice = e.UnitSalePrice 
     }); 

     return detailView.ToList(); 
    } 

、私は私が最終的な結果をフィルタリングするために使用するいくつかのコードを削除しました。それは、filterFields変数に渡され、linqクエリに追加された値を通過するif文の束です。もし誰かがそれが必要だと思ったら私はそれを投稿することができますが、エラーはフィルタ値が存在する前にこのデータを表示しているページに初めて当たったときに発生します。

さらに詳しい情報を提供できる場合は、私にお知らせください。

は、

ジョンNorcottありがとう

答えて

0

あなたはまだ、外部キー(HeaderID)がマッピングされ、あなたのモデルを持っています。ヘッダーIDまたはヘッダーのいずれかをプロパティとして持ちますが、両方を持たないようにしてください。

モデルから、それを削除します。

public class POSErrorQueueDetail 
{ 
    public virtual Int32 DetailID { get; set; } 
    public virtual POSErrorQueue Header { get; set; } 
} 

をちょうどHeader.HeaderIDにアクセスHeaderIDにアクセスします。そしてマッピング:

<?xml version="1.0" encoding="utf-8" ?> 
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" assembly="TPMControlPanel" namespace ="TPMControlPanel.Models"> 
    <class name="POSErrorQueueDetail" table="POSErrorQueueDetails"> 
    <id name="DetailID"> 
     <generator class="identity" /> 
    </id> 
    <!--all other property mappings removed for brevity --> 
    <many-to-one name="Header" class="POSErrorQueue" column="HeaderID" fetch="join" /> 
    </class> 
</hibernate-mapping> 
+0

それでした!ありがとう!ただし、これはデータベース内のdetailLine.HeaderID列をマップしていないため、必要に応じて、詳細行を別のヘッダーに移動するにはどうすればよいのでしょうか?これは、私がこの時点で持っている問題ではなく、このソリューションがもたらす好奇心の多くです。 –

+0

これは実装に依存しますが、基本的には、あるヘッダの詳細コレクションから詳細行を削除し、それを他のヘッダの詳細コレクションに追加します。途中で、ヘッダーへのディテールの参照を変更する必要があります。 –

関連する問題