7

FormView を更新しようとすると、このエラーが発生します

ObjectDataSource 'odsForm' の DataObjectTypeName プロパティで指定されたタイプの 'MainContact.FirstName' という名前のプロパティが見つかりませんでした。

EditTemplate でこのような Textbox を使用しているためだと思います

<asp:TextBox Text='<%# Bind("MainContact.FirstName") %>' ID="txtFirstName" runat="server" />

テキストボックスに正しいテキストが表示されますが、更新すると機能しないようです。

これは FormView のデータソースです

<asp:ObjectDataSource ID="odsForm" runat="server" DataObjectTypeName="Helpers.BusinessObjects.EntryItem"
    SelectMethod="GetEntryByEmail" TypeName="Helpers.DataAccessers.EntryHelper"
    UpdateMethod="UpdateEntry">
    <SelectParameters>
        <asp:SessionParameter SessionField="email" Name="email" Type="String" />
    </SelectParameters>
</asp:ObjectDataSource>

これは EntryItem クラスです

 public class EntryItem
    {
        public int Id { get; set; }
        public string Email { get; set; }
        public string Password { get; set; }
        public Person MainContact { get; set; } 
        ...
    }

そして Person クラス

public class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    ...
}

デバッガーは FormViewItemUpdatingイベント ハンドラーを取得しますが、Helpers.DataAccessers.EntryHelper.UpdateEntry.

どうすればこれを解決できますか?

4

3 に答える 3

4

このように使用するために、必要に応じてバインディングを実行できる独自のコントロールを作成できます (私はこれの 1 つを作成しました)。

    <ItemTemplate>
      <%# Eval("MainContact.FirstName")%>
    </ItemTemplate>
    <EditItemTemplate>
      <xx:BinderHelper runat="server" DataSource='<%# Bind("MainContact") %>'>
        <ItemTemplate>
          <asp:TextBox Text='<%# Bind("FirstName") %>' ID="txtFirstName" 
             runat="server" />
        </ItemTemplate>
      </xx:BinderHelper>
    </EditItemTemplate>

とにかく、ドメインオブジェクトをページで直接使用しないこと、および全体として ObjectDataSource でそれらを記述しないことをお勧めします。問題は、たとえばフィールドを追加するためにドメインを変更する場合です。

public class Person
{
    public int Id { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }

    // just added
    public DateTime? BirthDate { get; set; }
}

次に、すべての GridViews、FormViews などを変更して BirthDate を格納する必要があります。そうしないと、フレームワークは ObjectDataSource Update メソッドを呼び出してnullBirthDate を挿入します。例えば:

<asp:GridView runat="server" DataSourceID="odsForm" AutoGenerateColumns="False">
    <Columns>
      <asp:CommandField runat="server" ShowEditButton="True" />
      <asp:BoundField DataField="FirstName" />
      <asp:BoundField DataField="LastName" />
 </Columns>
  </asp:GridView>

データベースからあなたの人を読み取ります。一人一人に生年月日が設定されます。null保存すると、GridView は新しいフィールドを保存しないため、人は BirthDate で に更新されます。

最良の解決策は、データバインディング用の DTO を作成し (プレゼンテーション層に残して)、DataObjects を作成することだと思います。あなたの場合:

public class EntryItemView
{
    public int Id { get; set; }
    public string Email { get; set; }
    public string Password { get; set; }
    public string MainContactFirstName { get; set; } 
}

[DataObject]
public class EntryItemViewDataObject {
   [DataObjectMethod(DataObjectMethodType.Select)]
   public EntryItemView GetItem(...) {
       // TODO: read from the database, convert to DTO
   }

   [DataObjectMethod(DataObjectMethodType.Update)]
   public void Update( EntryItemView entry) {

      EntryItem domainObject = getById(entry.Id);
      // TODO: use EmitMapper or AutoMapper
      domainObject.MainContact.FirstName = entry.MainContactFirstName;

      // TODO: save
   }
}

このようにして、ドメインへの追加はビューに対して安全になり、DataObjects は必要なフィールドのみを読み書きします。

于 2012-08-24T07:10:47.807 に答える
1

2 つの可能なアプローチ。

DataObjectTypeName="Helpers.BusinessObjects.EntryItem"まず、の定義から削除できますObjectDataSource。私はそれを使用したことがなく、バインディングは常に機能します。

しかし、Bind/Evalはおそらく参照をたどることができないため、これはおそらく役に立ちません ( Bind("MainContact.FirstName"))。

代わりに、これを次のように書き換えます。

<%# ((EntryItem)Container.DataItem).MainContract.FirstName #>

欠点は、自動双方向綴じが緩くなるため、バインダーを少し手伝わなければならないことです. Inserting/UpdatingObjectDataSource と内部ハンドラーにハンドラーを追加するだけです。

protected void TheObjectDataSource_Updating( object sender, BlahBlahEventArgs e )
{
    // find the control in the data bound parent
    TextBox txt = (TextBox)YourFormView.FindControl( "txtFirstName" );

    // read the value and add it to parameters
    e.Parameters.Add( "nameofyourparameter", txt.Text );
}
于 2012-08-21T18:25:40.573 に答える
0

いくつかの情報源によると、ネストされたプロパティを使用して双方向バインディングを実行することは実際には不可能です。

SOに関する同様の質問に対する1つの回答があります:https ://stackoverflow.com/a/1195119/370671 。

また、この問題を説明するブログ投稿があります。

さて、それでもほとんどの場合、ObjectDataSourceバインドするものがクライアントの名前などの単純なプロパティである場合、使用しても問題は発生しません。つまり、バインドするクライアントのコレクションがGridViewあり、列の1つにクライアントの名前。そのためには、のようなものを使用しますBind("Name")。この問題は、などのサブプロパティにバインドする必要がある場合に発生します Bind("Address.StreetName")。これは機能しません

于 2012-08-21T18:38:26.357 に答える