【问题标题】:Using Joins and Nested Repeaters with SQL Server?在 SQL Server 中使用联接和嵌套中继器?
【发布时间】:2017-11-02 22:28:33
【问题描述】:

我正在尝试创建一个 Employee Scheduler,但在显示数据时遇到了一些问题。

我想先显示 Schedule_Dates,然后在其下方显示当天将发生的 Job_Types。

然后,我尝试显示该计划的 Employee_NameStart_TimeEnd_Time

到目前为止,我已显示日期和工作类型,但在尝试显示员工姓名和开始/结束轮班时间时遇到了问题。

以下是我当前的输出:

这是我当前的 C#:

 private void bindRepeaterPerPerson()
{
    conn = new SqlConnection(connectionString);
    conn.Open();
    comm = new SqlCommand("SELECT DISTINCT Start_Date, End_Date FROM My_Subscription WHERE Subscription_Id = 1", conn);
    SqlDataReader reader = comm.ExecuteReader();
    while (reader.Read())
    {
        startDate = Convert.ToDateTime(reader["Start_Date"]);
        endDate = Convert.ToDateTime(reader["End_Date"]);
    }
    conn.Close();
    using (SqlConnection con = new SqlConnection(connectionString))
    { 
        using (SqlCommand cmd = new SqlCommand("SELECT DISTINCT CAST(Schedule_Date AS DATE) As Schedule_Date FROM My_Employee_Schedule WHERE Start_Time BETWEEN @startReportDate AND @endReportDate", con))
        {
            cmd.Parameters.AddWithValue("@startReportDate", startDate);
            cmd.Parameters.AddWithValue("@endReportDate", endDate);
            using (SqlDataAdapter sda = new SqlDataAdapter(cmd))
            {
                DataTable dt = new DataTable();
                sda.Fill(dt);
                repSubscription1.DataSource = dt;
                repSubscription1.DataBind();
            }
        }
    }
}

protected void repSubscription1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    conn = new SqlConnection(connectionString);
    conn.Open();

    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
    {
        Repeater repJobs = (Repeater)(e.Item.FindControl("repJobs"));
        SqlCommand cmd = new SqlCommand("SELECT DISTINCT j.Job_Title FROM [dbo].[My_Employee_Schedule] as s INNER JOIN My_Job_Type j on s.Job_ID = j.Job_Type_Id WHERE Schedule_Date = @Date", conn);
        DateTime myDate = Convert.ToDateTime(DataBinder.Eval(e.Item.DataItem, "Schedule_Date"));
        cmd.Parameters.AddWithValue("@Date", myDate);
        SqlDataAdapter sda = new SqlDataAdapter(cmd);
        DataTable dt = new DataTable();
        sda.Fill(dt);
        repJobs.DataSource = dt;
        repJobs.DataBind();
    }
    conn.Close(); 
}

HTML:

 <asp:Repeater ID="repSubscription1" runat="server" OnItemDataBound="repSubscription1_ItemDataBound">
                    <ItemTemplate>
                        <div class="col-lg-2">
                            <div class="panel panel-default">
                                <div class="panel-heading" style="background-color: #3A6EA5; color: white">
                                    <h4 class="panel-title">
                                        <%# Eval("Schedule_Date", "{0:dddd, dd MMMM yyyy}") %>
                                    </h4>
                                </div>
                                <!--panel-heading-->
                                <div class="panel-body">
                                    <asp:Repeater ID="repJobs" runat="server">
                                        <ItemTemplate>
                                            <%# Eval("Job_Title") %>
                                            <br /><br />
                                        </ItemTemplate>
                                    </asp:Repeater>

                                </div>
                                <!--panel-body-->
                            </div>
                            <!--panel-default-->
                        </div>
                        <!--col-lg-2-->
                    </ItemTemplate>
                </asp:Repeater>

以下是我的 SQL 表:

CREATE TABLE [dbo].[My_Employee_Schedule] (
[Emp_Sch_Id]    INT      IDENTITY (1, 1) NOT NULL,
[Schedule_Date] DATETIME NULL,
[Start_Time]    DATETIME NULL,
[End_Time]      DATETIME NULL,
[Emp_ID]        INT      NULL,
[Job_ID]        INT      NULL,
PRIMARY KEY CLUSTERED ([Emp_Sch_Id] ASC),
FOREIGN KEY ([Emp_ID]) REFERENCES [dbo].[My_Employee] ([Employee_Id]) ON 
DELETE CASCADE,
FOREIGN KEY ([Job_ID]) REFERENCES [dbo].[My_Job_Type] ([Job_Type_Id]) ON 
DELETE CASCADE
);

CREATE TABLE [dbo].[My_Job_Type] (
[Job_Type_Id] INT           IDENTITY (1, 1) NOT NULL,
[Job_Title]   NVARCHAR (50) NOT NULL,
 PRIMARY KEY CLUSTERED ([Job_Type_Id] ASC)
);

CREATE TABLE [dbo].[My_Employee] (
[Employee_Id]   INT           IDENTITY (1, 1) NOT NULL,
[Employee_Name] NVARCHAR (50) NOT NULL,
[Company_Id]    INT           NOT NULL,
PRIMARY KEY CLUSTERED ([Employee_Id] ASC),
FOREIGN KEY ([Company_Id]) REFERENCES [dbo].[My_Company] ([Company_Id]) ON DELETE CASCADE
);

还有,我的表格数据:

Emp_Sch_Id  | Schedule_Date       | Start_Time          | End_Time            | Emp_ID | Job_ID
------------------------------------------------------------------------------------------------
1           | 03/06/2017 00:00:00 | 03/06/2017 09:00:00 | 03/06/2017 10:00:00 | 5      |  2
2           | 03/06/2017 00:00:00 | 03/06/2017 11:30:00 | 03/06/2017 12:30:00 | 6      |  1
3           | 03/06/2017 00:00:00 | 03/06/2017 14:00:00 | 03/06/2017 15:00:00 | 5      |  3
4           | 03/06/2017 00:00:00 | 03/06/2017 12:00:00 | 03/06/2017 13:00:00 | 4      |  2
5           | 03/06/2017 00:00:00 | 03/06/2017 12:15:00 | 03/06/2017 15:15:00 | 4      |  2

Employee_Id | Employee_Name
----------------------------
4           | Damien
5           | John
6           | Owen

【问题讨论】:

  • 您可以通过不使用 DataTables 使整个事情变得更容易。使用强类型模型对象,并将它们绑定到您的转发器。
  • @mason 嗨,你能提供这些强类型模型对象的链接吗?我以前没有和他们合作过。这些是否适用于多个 SQL 表?
  • 我打赌你有。我只是在谈论一个描述你的对象的类。而已。只是一个普通的老班。然后将其绑定为 DataSource 而不是使用 DataTable。
  • @mason 那么我要从数据库中检索数据并用它创建一个类的实例吗?
  • 是的,没错。这不应该在您的页面代码中完成。在其他地方有一个数据层来处理它。

标签: c# asp.net sql-server


【解决方案1】:

首先,安装 dapper(或其他 ORM),然后创建模型:

public class MyData 
{
    public DateTime Schedule_Date {get;set;}
    public DateTime Start_Time {get;set;}
    public DateTime End_Time {get;set;}
    public string Employee_Name {get;set;}
    public string Job_Title {get;set;}
}

创建你的 DAL 类:

public class DAL
{
    public static string connectionString = ...;

    public IEnumerable<MyData> GetMyClassByRange(DateTime start, DateTime end)
    {
        var sql = @"SELECT Schedule_Date, Start_Time, End_Time, Employee_Name, Job_Title
                    FROM My_Employee_Schedule ed
                    JOIN My_Employee e ON ed.Emp_ID = e.Employee_Id
                    JOIN My_Job_Type jt ON ed.Job_ID = jt.Job_Type_Id
                    WHERE Start_Time BETWEEN @startReportDate AND @endReportDate";

        conn = new SqlConnection(connectionString);
        conn.Open();

        var data = conn.Query<MyData>(sql, new { startReportDate=startDate, endReportDate=endDate});
        conn.Close();
    }
}

好的,现在您已经有了 DAL,您可以将其调整为您想要的形式,即按日期,然后按工作,以及员工及其开始日期。因此,让我们继续在您的页面代码中执行此操作:

public IEnumerable<MyViewModel> GetData()
{
    //var test = new List<MyData>();
    //test.Add(new MyData { Schedule_Date = new DateTime(2017, 6, 3), Start_Time = new DateTime(2017, 6, 3, 9, 0, 0), End_Time = new DateTime(2017, 6, 3, 10, 0, 0), Job_Title = "Waiter", Employee_Name = "John" });
    //test.Add(new MyData { Schedule_Date = new DateTime(2017, 6, 3), Start_Time = new DateTime(2017, 6, 3, 11, 0, 0), End_Time = new DateTime(2017, 6, 3, 12, 0, 0), Job_Title = "Driver", Employee_Name = "Own" });
    //test.Add(new MyData { Schedule_Date = new DateTime(2017, 6, 3), Start_Time = new DateTime(2017, 6, 3, 14, 0, 0), End_Time = new DateTime(2017, 6, 3, 15, 0, 0), Job_Title = "Busser", Employee_Name = "John" });
    //test.Add(new MyData { Schedule_Date = new DateTime(2017, 6, 3), Start_Time = new DateTime(2017, 6, 3, 12, 0, 0), End_Time = new DateTime(2017, 6, 3, 13, 0, 0), Job_Title = "Waiter", Employee_Name = "Damien" });
    //test.Add(new MyData { Schedule_Date = new DateTime(2017, 6, 3), Start_Time = new DateTime(2017, 6, 3, 12, 15, 0), End_Time = new DateTime(2017, 6, 3, 15, 15, 0), Job_Title = "Waiter", Employee_Name = "Damien" });
    var MyDal = new DAL();
    var test = MyDal.GetMyClassRange(DateTime.Now, DateTime.Now.AddYears(1));
    var result = test
        .GroupBy(x => new {x.Schedule_Date, x.Job_Title})
        .GroupBy(x => x.Key.Schedule_Date)
        .Select(x => new MyViewModel {Start_Date = x.Key, Jobs = x.Select(y => new MyJobsView {Job_Title = y.Key.Job_Title, Datas = y})})
        .ToList();

    return result;
}

现在让我们制作中继器并将其全部绑定:

<asp:Repeater ID="rptDate" runat="server" ItemType="WebApplication1.MyViewModel" SelectMethod="GetData">
    <ItemTemplate>
        <br/>
        Start Date: <%# Item.Start_Date %>
        <asp:Repeater runat="server" ID="rptJob" ItemType="WebApplication1.MyJobsView" DataSource="<%# Item.Jobs %>">
            <ItemTemplate>
                <br/>Job Title: <%# Item.Job_Title %>
                <asp:Repeater runat="server" ID="rptJob" ItemType="WebApplication1.MyData" DataSource="<%# Item.Datas %>">
                    <ItemTemplate>
                        Name: <%# Item.Employee_Name %>
                        Start: <%# Item.Start_Time %>
                    </ItemTemplate>
                </asp:Repeater>
            </ItemTemplate>
        </asp:Repeater>
    </ItemTemplate>
</asp:Repeater>

【讨论】:

  • 非常感谢,如果这有效,那么它确实可以解决问题!我可以把这个 MyData 类放在 Default.aspx 的底部还是需要为此创建一个新位置?还有,第二段代码去哪了?
  • @user2911539 你把它放在哪里完全取决于你。但如果它是可重用的,那就不要把它放在你页面的代码后面。
  • @mason 谢谢。我在哪里放置上面提到的其他代码? var sql = @"...?
  • 老实说,使用实体框架作为 ORM 会更容易,但我使用 dapper 作为示例,因为它更底层(并且更容易解释)
  • @RobertMcKee 好的,你能了解如何从聊天表中填充类吗?我以前没有这样做过,我不知道如何进行
猜你喜欢
  • 2014-06-26
  • 2020-12-01
  • 2011-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多