2012-04-17 10 views
7

que tienen este error cuando trato de actualizar un FormViewNo se pudo encontrar una propiedad denominada 'xxx.yyy' en FormView (bidireccional vinculante para las propiedades anidadas)

No se pudo encontrar una propiedad denominada 'MainContact .FirstName 'en el tipo especificado por la propiedad DataObjectTypeName en ObjectDataSource ' odsForm '.

creo que es porque uso en el EditTemplate un cuadro de texto como éste

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

Muestra el texto a la derecha en el cuadro de texto, pero al parecer no funciona cuando se actualiza.

Esta es la fuente de datos de la 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> 

Ésta es la clase EntryItem

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

y la clase de persona

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

El depurador se interpone en el controlador de eventos FormView ItemUpdating , pero nunca en Helpers.DataAccessers.EntryHelper.UpdateEntry.

¿Cómo puedo solucionar esto?

Respuesta

1

Dos posibles enfoques.

En primer lugar, podría eliminar DataObjectTypeName="Helpers.BusinessObjects.EntryItem" de la definición de su ObjectDataSource. NUNCA LO he usado y las fijaciones siempre funcionan.

Pero esto probablemente no ayude, ya que el Bind/Eval probablemente no pueda seguir las referencias (Bind("MainContact.FirstName")).

En cambio, vuelve a escribir esto como

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

La desventaja es que usted bidireccional automática suelta vinculante lo que tiene que ayudar al ligante un poco. Sólo tiene que añadir Inserting/Updating manipuladores a su ObjectDataSource y en el interior manipuladores:

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); 
} 
0

De acuerdo con un par de fuentes, que en realidad no es posible hacer la unión con propiedades anidadas bidireccional.

Aquí hay una respuesta a una pregunta similar aquí en SO: https://stackoverflow.com/a/1195119/370671.

Además, there's a blog post que describe el tema:

Ahora, siendo en la mayoría de los casos el uso de ObjectDataSource no le causa ningún problema cuando lo [que] se unen es una propiedad simple, como un nombre de un ejemplo de cliente: tiene una colección de clientes que vincula a un GridView y una de las columnas muestra el nombre del cliente. Para hacerlo, usa algo como Bind("Name"). El problema surge cuando necesita vincularse a una subpropiedad como en Bind("Address.StreetName").Esto no funcionará

4

Usted puede escribir su propio control capaz de realizar la unión como desee, para ser utilizado de esta manera (hice uno de esto):

<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> 

De todos modos, te sugiero no usar objetos de dominio directamente en las páginas, y en general para no escribirlos con ObjectDataSource. El problema es que cuando se va a cambiar su dominio, por ejemplo, para añadir un campo:

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; } 
} 

A continuación, tendrá que cambiar todos los GridViews, FormViews, etc, para almacenar la fecha de nacimiento, de lo contrario el marco llamará a su ObjectDataSource Método de actualización poniendo null en el BirthDate. Por ejemplo:

<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> 

Leerá a sus personas de la base de datos. Cada persona tendrá una fecha de nacimiento establecida. Cuando guarde, la persona se actualizará con BirthDate al null, porque el GridView no almacena el nuevo campo.

Creo que la mejor solución es escribir DTO para el enlace de datos (y dejarlos en la capa de presentación) y DataObjects. En su caso:

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 
    } 
} 

De esta manera cualquier adición a su dominio será seguro para sus puntos de vista, y DataObjects van a leer/escribir sólo los campos que necesitan.

+0

+1: Siempre me quemo perdiendo el tiempo con 'ObjectDataSource'. Espero que la próxima vez recuerde no molestarme con ellos. – capdragon

Cuestiones relacionadas