0


1

レポート作成用の汎用ViewModelへのデータ投入

私はいくつかのレポートを生成する必要があります、そしてそれらの多くは単に私のデータベースからのエンティティのテーブルになるでしょう。 実体はどんな種類のものでもよく、実体全体が常に必要なわけではありません。

私の現在のアプローチは、 `+ List> +`タイプのフィールドを含むViewModelを作成することです。これは、各行がセルのリストであるテーブルを表します。 その後、ビューは各行と列を列挙してテーブルを作成するだけで済みます。

public class ListReportViewModel
{
    public string Title;
    public List Headings;
    public List> 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();
data.Headings.Add( "Ticket ID" );
data.Headings.Add( "Company" );
data.Headings.Add( "Caller" );
data.Headings.Add( "Reason for Call" );

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

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

    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> +`を返すことができれば、「 `+ data.Rows = ticket +」という行を使用するだけで、ビュー自体がこれをループできるようになります。

私はこれを行うためのもっと良い方法があるに違いないと思います。

2 Answer


1


リフレクションを使用したい場合は、私のプロジェクトをcodeplex mvcrendermodelで試してください。

オブジェクトのリストがテーブルとして表示されます。

私はデバッグを容易にするためにプロジェクトを構築しており、一般的には本番には役に立ちませんが、トラフィックが限られている場合は問題ないはずです。


0


これが私がMathiasの提案を見た後に思いついた解決策です。 世界で最も速いものではありませんが、今のところ十分な速さです。

タイプと見出しのない辞書なしで `+ IEnumerable +`を使用するようにViewModelを変更しました:

ListReportViewModel.cs

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

私のコントローラでは、通常の方法でエンティティを選択し、見出し辞書を設定して、レポートの内容を定義します。

ReportController.cs

var data = new ListReportViewModel();

data.Title = "Closed Calls";

data.Headings = new Dictionary();
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( "" + Html.Encode( propObject.ToString() ) + "

"();} catch(NullReferenceException)\ {Response.Write("

 — --

");}}}