Заполнение универсальной модели представления для построения отчетов - PullRequest
0 голосов
/ 10 июня 2009

Мне нужно создать несколько отчетов, и многие из них будут просто таблицами сущностей из моей базы данных. Объекты могут быть любого типа, и мне не всегда понадобится весь объект.

Мой текущий подход заключается в создании ViewModel, который содержит поле типа List<List<string>>, которое представляет мою таблицу, где каждая строка представляет собой список ячеек. Затем представлению нужно только перечислить все строки и столбцы для создания таблицы.

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<IEnumerable<string>>, то я мог бы просто использовать строку "data.Rows = tickets", и представление могло бы проходить через это само.

Я думаю, что должен быть лучший способ сделать это, о котором я не знаю.

Ответы [ 2 ]

1 голос
/ 11 июня 2009

Если вы хотите использовать отражение, попробуйте мой проект в codeplex mvcrendermodel

Отображает список объектов в виде таблицы.

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

0 голосов
/ 12 июня 2009

Вот решение, которое я придумала после просмотра предложения Матиаса. Не самая быстрая вещь в мире, но пока достаточно быстрая.

Я изменил свою 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>" );
        }

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