【问题标题】:Populating a generic ViewModel for building reports填充通用 ViewModel 以构建报告
【发布时间】:2009-06-10 19:33:10
【问题描述】:

我需要生成几份报告,其中许多只是我的数据库中的实体表。实体可以是任何类型,我并不总是需要整个实体。

我目前的方法是创建一个包含List<List<string>> 类型字段的 ViewModel,它代表我的表格,其中每一行都是一个单元格列表。然后,视图只需要遍历每一行和每一列来创建表。

public class ListReportViewModel
{
    public string Title;
    public List<string> Headings;
    public List<List<string>> Rows;
}

然后我有控制器代码来填充标题和行:

// Get the entities for the report
var tickets = ( from t in _db.Ticket.Include("Company").Include("Caller")
              select t );    

// Populate the column headings
data.Headings = new List<string>();
data.Headings.Add( "Ticket ID" );
data.Headings.Add( "Company" );
data.Headings.Add( "Caller" );
data.Headings.Add( "Reason for Call" );

// Temporary staging variables
List<List<string>> rows = new List<List<string>>();
List<string> row;

// Populate temporary variables
foreach ( var ticket in tickets )
{
    row = new List<string>();

    row.Add( ticket.TicketID.ToString() );
    row.Add( ticket.Company.Name );
    row.Add( ticket.Caller.FirstName + " " + ticket.Caller.LastName );
    row.Add( ticket.Subject );

    rows.Add( row );
}

// Populate ViewModel field
data.Rows = rows;

虽然这样可行,但似乎效率低下。我遍历整个结果集只是为了填充 ViewModel,然后视图将不得不再次遍历它来构建报告。

我的问题:有没有更简单的方法可以做到这一点?如果我可以让我的 Linq 查询返回一个 IEnumerable&lt;IEnumerable&lt;string&gt;&gt;,那么我可以只使用“data.Rows = tickets”这一行,并且视图本身就能够循环遍历它。

我认为一定有更好的方法来做到这一点,我不知道。

【问题讨论】:

    标签: c# asp.net-mvc linq linq-to-entities


    【解决方案1】:

    如果您愿意使用反射,请在 codeplex mvcrendermodel 中试用我的项目

    它将对象列表显示为表格。

    我构建这个项目是为了更容易调试,它通常对生产没有用,但如果你只有有限的流量应该没问题。

    【讨论】:

    • 你的扩展方法很有趣,+1 引导我使用反射。谢谢!不过,这并没有为我提供我所需要的报告。
    • 很高兴听到它对您有用。如果您遗漏了其中的某些内容,请在 codeplex 上留言。
    【解决方案2】:

    这是我在查看 Mathias 的建议后提出的解决方案。不是世界上最快的东西,但现在已经足够快了。

    我更改了我的 ViewModel 以使用 IEnumerable 没有类型和标题字典:

    ListReportViewModel.cs

    public class ListReportViewModel
    {
        public string Title;
        public Dictionary<string,string> Headings;
        public IEnumerable Data;
    }
    

    在我的控制器中,我以正常方式选择实体,并填充标题字典以定义我想要报告的内容:

    ReportController.cs

    var data = new ListReportViewModel();
    
    data.Title = "Closed Calls";
    
    data.Headings = new Dictionary<string, string>();
    data.Headings.Add( "TicketID", "ID" );
    data.Headings.Add( "Company.Name", "Company" );
    data.Headings.Add( "Caller.FirstName", "Caller" );
    data.Headings.Add( "Subject", "Reason for Call" );
    data.Headings.Add( "ClosedTime", "Closed" );
    data.Headings.Add( "ClosedBy.LoginName", "Closed By" );
    
    data.Data = ( from t in _db.Ticket.Include( "Company" ).Include( "Caller" ).Include( "ClosedBy" )
                  where !t.Open
                  orderby t.ClosedTime ascending
                  select t );
    
    return View( "list", data );
    

    然后,处理的核心由视图完成,以搅动 ViewModel 并填充表格:

    list.aspx

    bool isFirstRow = true;
    Type rowType = typeof( System.Data.Objects.DataClasses.EntityObject );
    Type propType;
    System.Reflection.PropertyInfo propInfo;
    object propObject;
    string[] propNames;
    
    foreach ( var row in Model.Data )
    {
        if ( isFirstRow )
        {
            // Get the type of entity we're enumerating through
            rowType = row.GetType();
            isFirstRow = false;
        }
    
        // Enumerate through the columns
        foreach ( var kvp in Model.Headings )
        {
            propNames = kvp.Key.Split( '.' );
            propObject = row;
            propType = rowType;
    
            // Drill down through the entity properties so we can
            // handle properties like "Ticket.Company.Name"
            foreach ( var propName in propNames )
            {
                try
                {
                    propInfo = propType.GetProperty( propName );
                    propObject = propInfo.GetValue( propObject, null );
                    propType = propObject.GetType();
                }
                catch ( NullReferenceException ) { }
            }
    
            try
            {
                Response.Write( "<td>" + Html.Encode( propObject.ToString() ) + "</td>" );
            }
            catch ( NullReferenceException )
            {
                Response.Write( "<td>--</td>" );
            }
    
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-01
      • 2019-12-21
      • 1970-01-01
      相关资源
      最近更新 更多