使用LINQ从FK相关表访问信息

时间:2009-05-06 02:31:30

标签: c# asp.net linq linq-to-sql database-design

我正在研究员工调度系统。我认为我的数据库设置非常好,并且在为我的数据库提取数据并将其放到页面上时遇到了麻烦。我正在使用LINQ让自己变得轻松。

Here是对象关系图。

这是我的Linq select语句:

protected void LinqSelecting(object sender, LinqDataSourceSelectEventArgs e) {
    MilhouseDataClassesDataContext mdb = new MilhouseDataClassesDataContext();
    e.Result = from x in mdb.MilhouseHours
               group x by x.HourString into hour
               select new {
                   hourStr=hour.Key,
                   uName=hour};
 }

以下是我的GridView代码的相关部分:

        <asp:GridView ID="GridView1" runat="server" DataSourceID="LinqDataSource1" AutoGenerateColumns="false">
            <asp:TemplateField HeaderText="Sunday">
                <ItemTemplate>
                    <asp:CheckBoxList ID="shiftsSun" runat="server" DataSource='<%#Eval("uName")%>' DataValueField="UserId" />
                </ItemTemplate>
            </asp:TemplateField>
            ...
        </asp:Gridview>

这将正确显示数据库中的UserId,但我希望它显示UserName。我实现此显示的唯一方法是将我的组语句更改为:

group x.aspnet_User by x.HourString into hour

我想我在这里错过了一个大概念。通过使用group,我应该可以通过我的匿名类的uName成员访问aspnet_user类成员......或者我认为!

编辑:以下是调试时捕获的变量的几个屏幕截图。

e.Result | aspnet_User

我的最终目标是建立一个gridview,它将显示每个单元格中x小时y工作班次的列表。任何设计或代码帮助将不胜感激。我似乎无法理解这一点。

2 个答案:

答案 0 :(得分:2)

迭代包含MilhouseHour对象的集合:IGrouping。 MilhouseHour确实包含对aspnet_User的引用,但是你要引用的东西,名称(和id)是aspnet_User的属性,而不是MilhouseHour。理想情况下,您可以编写像

这样的标记
  <asp:CheckBoxList ID="shiftsSun" runat="server" 
    DataSource='<%#Eval("hourUsers")%>' 
    DataTextField = "aspnet_User.UserName"
    DataValueField = "aspnet_User.UserId" />

但这会产生错误。 ASP.Net期望在DataTextField中它将在有问题的对象上调用(可能是通过反射)的属性的名称,而不是要评估的表达式。有问题的对象是MilhouseHour,它没有名为“aspnet_User.UserName”的属性。

您有很多选择。

  1. 执行您最初执行的操作,并在LINQ表达式中将x.aspnet_User分组而不是x。然后由CheckBoxList迭代的东西将是一个IGrouping,它将具有可用的属性“UserName”和“UserId”。
  2. 避免使用CheckBoxList并使用一些可以让您更明确地控制内部循环中的代码的内容,例如repeater:

    <asp:TemplateField HeaderText="Sunday">
    <ItemTemplate>
        <asp:Repeater ID="shiftsSun" runat="server" DataSource='<%#Eval("hourUsers")%>'>
            <ItemTemplate>
                <asp:CheckBox runat="server" 
                   Text='<%# Eval("aspnet_User.UserName")  %>' 
                   Value='<%# Eval("aspnet_User.UserId") %>' />
                <br />
            </ItemTemplate>
        </asp:Repeater>
    </ItemTemplate>
    

  3. 可能还有更多选择,但这就是我现在所遇到的情况。

答案 1 :(得分:1)

我认为你没有遗漏任何重大概念。组查询生成IGrouping的集合,其中无论MilhouseHours集合中的对象类型是什么。 (我无法为您的对象模型获得更大的图片。)然后将这些分组绑定到CheckBoxList的数据源。您缺少DataTextField =“NameField”指令,但没有主要概念。这里有一些有用的代码,至少与你的问题有关,如果不相同的话:

        <asp:GridView ID="myGrid" runat="server" AutoGenerateColumns="false">
        <Columns>
            <asp:TemplateField>
                <ItemTemplate>
                    <%# Eval("hourUsers.Key") %>
                </ItemTemplate>
            </asp:TemplateField>

            <asp:TemplateField HeaderText="Sunday">
                <ItemTemplate>
                    <asp:CheckBoxList ID="shiftsSun" runat="server" 
                        DataSource='<%#Eval("hourUsers")%>' 
                        DataTextField = "Name"
                        DataValueField = "Id" />
                </ItemTemplate>
            </asp:TemplateField>
        </Columns>
    </asp:GridView>

在页面背后:

    class UserHour
    {
        public string Name {get;set;}
        public int Id { get; set; }
        public string Hour { get; set; }
    }

    protected void Page_Load(object sender, EventArgs e)
    {
        var users = new List<UserHour>
                        {
                                    new UserHour {Name = "Fred", Id = 1, Hour = "0800"},
                                    new UserHour {Name = "Fred", Id = 1, Hour = "0900"},
                                    new UserHour {Name = "Fred", Id = 1, Hour = "1000"},
                                    new UserHour {Name = "Bob", Id = 2, Hour = "0900"},
                                    new UserHour {Name = "Bob", Id = 2, Hour = "1000"},
                        };
        var result = from x in users
                     group x by x.Hour
                     into hour select new
                                          {
                                                      hourStr = hour.Key, hourUsers = hour
                                          };

        myGrid.DataSource = result;
        myGrid.DataBind();
    }