2015-09-01 4 views
1

У меня возникли проблемы с отображением поля объекта одного из моих объектов в приложении asp.net. DataBinder.Eval возвращение Nothing почему-то.DataBinder.Eval возвращает null, хотя поле заполнено

У меня есть 2 классов следующим образом:

Public Class Bench 
    <ScaffoldColumn(False), StringLength(50), Key> _ 
    Public Property Code() As String 

    <Required> _ 
    Public Property Type() As BenchType 

    <Required, StringLength(50)> _ 
    Public Property Name() As String 

    ... 
End Class 

Public Class BenchType 
    <ScaffoldColumn(False), Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)> _ 
    Public Property ID() As Integer 

    <Required, StringLength(50)> _ 
    Public Property Name() As String 

    ... 
End Class 

Я пытаюсь отобразить Bench объекты в GridView следующим образом (с правильно реализован ObjectDataSourceodsBenches):

<asp:GridView ID="grwBenches" runat="server" DataSourceID="odsBenches" 
    DataKeyNames="Code,Type,Name" AutoGenerateColumns="false"> 
    <Columns> 
     <asp:TemplateField HeaderText="Code"> 
      <ItemTemplate> 
       <asp:Label id="lblCode" runat="server" Text='<%# Bind("Code")%>'></asp:Label> 
      </ItemTemplate> 
     </asp:TemplateField> 
     <asp:TemplateField HeaderText="Name"> 
      <ItemTemplate> 
       <asp:Label id="lblName" runat="server" Text='<%# Bind("Name")%>'></asp:Label> 
      </ItemTemplate> 
     </asp:TemplateField> 
     <asp:TemplateField HeaderText="Bench Type"> 
      <ItemTemplate> 
       <asp:Label id="lblBenchType" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "Type.Name")%>'> 
       </asp:Label> 
      </ItemTemplate> 
     </asp:TemplateField> 
    </Columns> 
</asp:GridView> 

Code и Name поля отображаются в порядке, но поле Type показано как пустое, это результирующая разметка с отображаемой страницы:

<table cellspacing="0" rules="all" border="1" id="MainContent_grwBenches" style="border-collapse:collapse;"> 
    <tr> 
     <th scope="col">Code</th><th scope="col">Name</th><th scope="col">Bench Type</th> 
    </tr><tr> 
     <td> 
       <span id="MainContent_grwBenches_lblCode_0">OK Code</span> 
      </td><td> 
       <span id="MainContent_grwBenches_lblName_0">OK Name</span> 
      </td><td> 
       <span id="MainContent_grwBenches_lblBenchType_0"></span> 
      </td> 
    </tr> 
</table> 

Когда я пошагово код, Оказывается, что <%# DataBinder.Eval(Container.DataItem, "Type.Name")%> возвращается Nothing, но когда я проверить базу данных, то Type поле содержит код типа.

В чем может быть проблема?

Edit (DAL код):

Public Function GetBenches() As IQueryable(Of Bench) 
    Return _db.BENCHES 
End Function 

_db Где находится объект DbContext.

+1

Вы можете попробовать <% # DataBinder.Eval ("Тип")%> и если это ничего (это должно быть результатом .ToString()), тогда ваш код возвращает экземпляр типа null. База данных в порядке не означает, что код в порядке. –

+0

Это действительно так, но я использую Entity Framework для автоматического создания базы данных из объектов. Что я должен проверить? – Teeracroptus

+1

В этом случае вы имеете в виду '<% # DataBinder.Eval (" Тип ")%>' ничего? В этом случае вы можете проверить небольшое консольное приложение, что происходит. Просто используйте метод, используемый ObjectDataSource, и отлаживайте полученный результат. Или, если вы используете SQL Server, посмотрите в профилировщике SQL Server. –

ответ

0

Похоже, что проблема обусловлена ​​следующим:

  • Объект BenchType не является сериализуемым
  • Метод SELECT использует ленивую загрузку вместо активной загрузки

Необходимо внести следующие изменения:

Изменение BenchType класс следующим образом:

<Serializable> _ 
Public Class BenchType 
    <ScaffoldColumn(False), Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)> _ 
    Public Property ID() As Integer 

    <Required, StringLength(50)> _ 
    Public Property Name() As String 

    ... 
End Class 

Изменить метод DAL SELECT следующим образом:

Public Function GetBenches() As IQueryable(Of Bench) 
    Return (From c In _db.BENCHES.Include("Type") Select c) 
End Function 
0

Не так ли?

<asp:Label id="lblBenchType" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "BenchType.Name")%>'> 

так

Public Property Type() As BenchType 
+0

Спасибо за предложение, попробовал, но не работал. 'BenchType' - это имя класса, оно должно быть именем свойства. – Teeracroptus

+0

Вы проверили, возвращает ли BenchType действительный идентификатор и имя? – RelatedRhymes

+0

Поле 'Type' возвращает' Nothing', поэтому поля 'ID' и' Name' не могут быть доступны – Teeracroptus

0

Это работает для меня.

<asp:TemplateField HeaderText="Bench Type"> 
     <ItemTemplate> 
      <asp:Label id="lblBenchType" runat="server" Text='<%# Bind("Type.Name")%>'></asp:Label> 
     </ItemTemplate> 
    </asp:TemplateField> 
0

Только слепой выстрел, но должен ли быть новый конструктор?

Public Class Bench 
    Public Sub new() 
     Me.Type=new BenchType 
    End Sub 


<ScaffoldColumn(False), StringLength(50), Key> _ 
Public Property Code() As String 

<Required> _ 
Public Property Type() As BenchType 

<Required, StringLength(50)> _ 
Public Property Name() As String 

... 
End Class 

Мне интересно, не заполнить базу данных, потому что класс не был создан.

+0

EF должно заполнять поле, поля «Name» и «Code» заполняются без особых усилий, есть что-то о 'Type' поле. – Teeracroptus

+0

Правильно, вы пытались? Тип не является родным полем, это класс. Если это явно не указано, это может вызвать ошибку создания экземпляра объекта. вы можете просто сгладить строку и иметь возможность установить ее значение, память выделяется «на лету». Не для класса. Вы можете попробовать изменить класс на структуру? – NINtender

0

Eval ищет имя объекта и имя свойства, и в этом случае объект является «Тип», а свойство «Имя». Поэтому, чтобы сделать длинный рассказ коротким, это должно сработать. Я думаю, проблема заключается в том, что «Тип» является зарезервированным ключевым словом. Попробуйте изменить название своего подкласса на что-то более описательное и посмотреть, не изменилось ли это. Надеюсь, это поможет.

<asp:TemplateField> 
    <ItemTemplate> 
     <asp:Label Id="lblSubclassVal" runat="server" Text="<%# DataBinder.Eval(Container.DataItem, "SubClass.PropertyName")%>"></asp:Label> 
    </ItemTemplate> 
</asp:TemplateField> 
+0

Я попытался изменить 'Type' на что-то еще, не работал. – Teeracroptus

0

В

[тип] является типом Определяемый пользователем

Public Property Type() As BenchType 

и

Public Class BenchType 
    <ScaffoldColumn(False), Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)> _ 
    Public Property ID() As Integer 

    <Required, StringLength(50)> _ 
    Public Property Name() As String 

    ... 
End Class 

Таким образом, вы не можете нормально связать этот тип в вас вид сетки, как

<asp:Label id="lblBenchType" runat="server" Text='<%# DataBinder.Eval(Container.DataItem, "Type.Name")%>'> 

или что-то вроде

<asp:Label id="lblBenchType" runat="server" Text='<%# Eval("Type.Name")%>'> 

Решение:

первый из все, вам нужно преобразовать данные результата в тип, а затем получите требуемое значение по его названию.

<asp:Label ID="lb1" runat="server" Text='<%# (Eval("Type") as BenchType).Name %>'></asp:Label> 

N: B Я не знаком с VB.NET, iv'e написал код в C#

+0

Я смог сделать это с помощью 'Text = '<% # Eval (" Type.Name ")%>'' с нетерпением загрузки и разрешить сериализацию. – Teeracroptus

+0

да, но так же простой и простой. @Teeracroptus –

+0

Благодарю вас за предложение. Это не сработает, если не загружать и сериализовать загрузку. – Teeracroptus

Смежные вопросы