C# 如何用linq构造动态查询

C# 如何用linq构造动态查询,c#,sql,asp.net-mvc,entity-framework,linq,C#,Sql,Asp.net Mvc,Entity Framework,Linq,我正试图建立一个数据集,我可以扔到一个电子表格,我必须承认,我已经达到饱和点!! 这些是我的桌子: **Matrix** Employee id Template id Expiry date **Employee** Id Employee Name **Template** Template Id Template Name 我试图实现的是一个所有员工的列表(其中员工将构成数据集的行)和一个所有模板的列表(模板是列头),然后我需要为每个模板的每个员工填充网格,并为每个模板填充其到期日

我正试图建立一个数据集,我可以扔到一个电子表格,我必须承认,我已经达到饱和点!! 这些是我的桌子:

**Matrix**
Employee id
Template id
Expiry date

**Employee** 
Id
Employee Name

**Template**
Template Id
Template Name
我试图实现的是一个所有员工的列表(其中员工将构成数据集的行)和一个所有模板的列表(模板是列头),然后我需要为每个模板的每个员工填充网格,并为每个模板填充其到期日期。一些员工没有每个模板的有效期,因为他们尚未获得认证

我在考虑创建一个员工列表,然后添加矩阵对象的employees集合,但这不一定有效,因为不是每个人都将每个模板类型作为矩阵中的条目

我在linq工作了几年,但我在这里有点困惑,因为这个数据集是如何动态构建的。定期添加新模板,因此需要在不维护查询的情况下添加新模板。使用linq是否可能,或者我是否需要考虑在SQL中构建视图

任何帮助都将不胜感激。下面是一个简单的例子,我正在尝试做什么

        Temp1       temp2       temp3       temp4
Emp1    01/01/2014  02/6/2015               04/06/2012
Emp2                02/6/2015           
Emp3    01/05/2010      
这是我的数据结构:

编辑

好吧,我确实设法得到了一些工作,我可以以我描述的格式输出到视图中,但我不知道它是否特别有效-如果有更好的方法,我想知道如何

   public class EmpMatrix
    {
        public int TemplateId { get; set; }
        public string TemplateName { get; set; }
        public DateTime? ExpiryDate { get; set; }
    }

    public class Classemptemp 
    {
        public emp Employee { get; set; }
        public List<EmpMatrix> tempateList { get; set; } 
    }

    public DateTime? GetExpiry(int template, int empl)
    {
        return (from a in _entities.matrices
            where a.empid == empl && a.tempId == template
            select a.expiryDate).FirstOrDefault();
    }


    public List<Classemptemp> testing()
    {
        List<emp> employees = _entities.emps.ToList();
        List<template> TemplateList = _entities.templates.ToList();
        List<Classemptemp> empList = (from employee in employees
            let matrix = TemplateList.Select(template => new EmpMatrix
            {
                TemplateId = template.templateId, TemplateName = template.Name, ExpiryDate = GetExpiry(template.templateId, employee.Id)
            }).ToList()
            select new Classemptemp
            {
                Employee = employee, tempateList = matrix
            }).ToList();
        return empList;
    }
公共类EMP矩阵
{
public int TemplateId{get;set;}
公共字符串TemplateName{get;set;}
公共日期时间?过期日期{get;set;}
}
公共类类emp
{
公共emp雇员{get;set;}
公共列表临时列表{get;set;}
}
公共约会时间?GetExpiry(int模板,int模板)
{
返回(来自于_entities.matrix中的
其中a.empid==emp&&a.tempId==template
选择a.expiryDate).FirstOrDefault();
}
公共列表测试()
{
列出员工=_entities.emps.ToList();
List TemplateList=_entities.templates.ToList();
列表雇员列表=(来自雇员中的雇员)
让矩阵=模板列表。选择(模板=>新矩阵
{
TemplateId=template.TemplateId,TemplateName=template.Name,ExpiryDate=GetExpiry(template.TemplateId,employee.Id)
})托利斯先生()
选择newclassemptemp
{
员工=员工,临时列表=矩阵
}).ToList();
返回雇主;
}
类(如果datacontext仍然存在,则将IEnumerable更改为IQueryable):

视图:

@model MyViewModel
@foreach(model.templates中的var模板)
{
@模板名称
}
@foreach(model.emps中的var emp)
{
@foreach(model.templates中的var模板)
{
@(emp.matrix.Any(m=>m.templateId==template.templateId)?
emp.matrix.First(m=>m.templateId==template.templateId).toString(“G”):
"")
}
}
类(如果datacontext仍然存在,则将IEnumerable更改为IQueryable):

视图:

@model MyViewModel
@foreach(model.templates中的var模板)
{
@模板名称
}
@foreach(model.emps中的var emp)
{
@foreach(model.templates中的var模板)
{
@(emp.matrix.Any(m=>m.templateId==template.templateId)?
emp.matrix.First(m=>m.templateId==template.templateId).toString(“G”):
"")
}
}

我想您可以使用System.Data.DataTable类并执行以下操作:

public class MatrixCell
{
    public string EmployeeName { get; set; }
    public string ColumnName { get; set; }
    public DateTime Date { get; set; }

    public DataTable ProcessRow(DataTable table)
    {
        bool found = false;

        foreach(DataRow row in table.Rows)
        {
            if ((string)row["Employeename"] == EmployeeName)
            {
                found = true;
                row[ColumnName] = Date;
                break;
            }
        }

        if(!found)
        {
            DataRow row = table.NewRow();
            row["Employeename"] = EmployeeName;
            row[ColumnName] = Date;
            table.Rows.Add(row);
        }

        return table;
    }
}
每个MatrixTable对象表示表中的一个单元格。 申请证明:

class Program
{
    static void Main(string[] args)
    {
        using (var db = new TestDB())
        {
            //Initialize DataTable
            DataTable table = new DataTable();
            var columnNames = db.Templates.Select(t => t.TemplateName).ToArray();

            table.Columns.Add("Employeename", typeof(string));

            foreach (var name in columnNames)
            {
                DataColumn column = new DataColumn(name, typeof(DateTime));
                column.AllowDBNull = true;
                table.Columns.Add(column);
            }

            //Get Matrix objects
            var result = db.Matrices.Select(m => new MatrixCell
            {
                ColumnName = m.Template.TemplateName,
                Date = (DateTime)m.Date,
                EmployeeName = m.Employee.EmployeeName
            }).ToArray();

            //Populate datatable
            foreach (var matrix in result)
                table = matrix.ProcessRow(table);

            Console.Read();
        }

    }
}
这将创建一个DataTable,其中templatenames作为列名称。每行代表一名员工,并填写相应模板的日期时间。然后可以将此数据表传递给视图以显示它

我希望这能奏效


编辑:我测试了几分贝的值,它似乎是工作。可以将
Employeename
设置为主键而不是列。

我想您可以使用System.Data.DataTable类并执行以下操作:

public class MatrixCell
{
    public string EmployeeName { get; set; }
    public string ColumnName { get; set; }
    public DateTime Date { get; set; }

    public DataTable ProcessRow(DataTable table)
    {
        bool found = false;

        foreach(DataRow row in table.Rows)
        {
            if ((string)row["Employeename"] == EmployeeName)
            {
                found = true;
                row[ColumnName] = Date;
                break;
            }
        }

        if(!found)
        {
            DataRow row = table.NewRow();
            row["Employeename"] = EmployeeName;
            row[ColumnName] = Date;
            table.Rows.Add(row);
        }

        return table;
    }
}
每个MatrixTable对象表示表中的一个单元格。 申请证明:

class Program
{
    static void Main(string[] args)
    {
        using (var db = new TestDB())
        {
            //Initialize DataTable
            DataTable table = new DataTable();
            var columnNames = db.Templates.Select(t => t.TemplateName).ToArray();

            table.Columns.Add("Employeename", typeof(string));

            foreach (var name in columnNames)
            {
                DataColumn column = new DataColumn(name, typeof(DateTime));
                column.AllowDBNull = true;
                table.Columns.Add(column);
            }

            //Get Matrix objects
            var result = db.Matrices.Select(m => new MatrixCell
            {
                ColumnName = m.Template.TemplateName,
                Date = (DateTime)m.Date,
                EmployeeName = m.Employee.EmployeeName
            }).ToArray();

            //Populate datatable
            foreach (var matrix in result)
                table = matrix.ProcessRow(table);

            Console.Read();
        }

    }
}
这将创建一个DataTable,其中templatenames作为列名称。每行代表一名员工,并填写相应模板的日期时间。然后可以将此数据表传递给视图以显示它

我希望这能奏效


编辑:我测试了几分贝的值,它似乎是工作。可以将
Employeename
设置为主键而不是列。

首先,是的,这似乎是可能的。然而,对于您已经拥有的代码,您有点含糊不清。你有DbContext吗?您是否绑定到视图?回答这个问题分为两个阶段,一个阶段:我需要什么查询,第二个阶段:我如何将数据表示为如上所述的表。我使用MVC,我将把查询结果绑定到数据网格,然后从控制器操作返回作为文件结果,以csv的形式将数据直接流回到客户端。我有一个包含每个表的EDMX,并使用_entites访问entites。所以我可以通过说_entities.employee.ToList()得到一个员工列表;我理解。你有导航属性吗?您的POCO类是什么样子的?是的,矩阵表templateId是模板表templateId的FK,而martix表employeeId是员工表Id的FK。所有Id字段都是int,过期日期是DateTime,员工姓名和模板名都是string。您考虑过使用导航属性吗<代码>公共雇员雇员{get;set;}首先,是的,这似乎是可能的。然而,对于您已经拥有的代码,您有点含糊不清。你有DbContext吗?您是否绑定到视图?有两只鹿
class Program
{
    static void Main(string[] args)
    {
        using (var db = new TestDB())
        {
            //Initialize DataTable
            DataTable table = new DataTable();
            var columnNames = db.Templates.Select(t => t.TemplateName).ToArray();

            table.Columns.Add("Employeename", typeof(string));

            foreach (var name in columnNames)
            {
                DataColumn column = new DataColumn(name, typeof(DateTime));
                column.AllowDBNull = true;
                table.Columns.Add(column);
            }

            //Get Matrix objects
            var result = db.Matrices.Select(m => new MatrixCell
            {
                ColumnName = m.Template.TemplateName,
                Date = (DateTime)m.Date,
                EmployeeName = m.Employee.EmployeeName
            }).ToArray();

            //Populate datatable
            foreach (var matrix in result)
                table = matrix.ProcessRow(table);

            Console.Read();
        }

    }
}