1

私は給油を追跡するアプリケーションに取り組んでいます。すべてのレコードには、ガソリンスタンドへの訪問に関するデータが保存されています。データベースに保存する情報をできるだけ少なくし、コントローラーで計算することにしました。

これは私のモデルです:

public class Refuel
{
    #region Properties

        public int id { get; set; }
        public int mileage { get; set; }
        public DateTime date { get; set; }
        public Nullable<double> volume { get; set; }
        public Nullable<double> price { get; set; }

        public Nullable<int> imageId { get; set; }
        public Nullable<int> gasstationId { get; set; }

        public virtual Gasstation Gasstation { get; set; }
        public virtual Image Image { get; set; }

    #endregion

    #region Methods

        public int distance { get; set; }

        [DisplayFormat(DataFormatString = "€ {0:0.00}")]
        public Nullable<double> totalPrice
        {
            get
            {
                return volume * price;
            }
        }

        [DisplayFormat(DataFormatString = "{0:0.00}")]
        public Nullable<double> consumption
        {
            get
            {
                if (distance > 0)
                    return volume / distance * 100;
                else
                    return 0;
            }
        }

        [DisplayFormat(DataFormatString = "{0:0}")]
        public Nullable<double> consumption2
        {
            get
            {
                if (distance > 0)
                    return distance / volume;
                else
                    return 0;
            }
        }

        [DisplayFormat(DataFormatString = "{0:0.00}")]
        public Nullable<double> mileageLeft
        {
            get 
            {
                return volumeLeft * consumption2;
            }
        }

        [DisplayFormat(DataFormatString = "{0:0.00}")]
        public Nullable<double> volumeLeft
        {
            get
            {
                double? d = 45 - volume;
                return d;
            }
        }

    #endregion
}

ご覧のとおり、ここの距離では何もしません。ある特定のレコードの詳細ページで距離を計算します。

私が今やりたいのは、インデックスページで距離を合計した要約を作成し、平均消費量を計算することです。これはすべて距離に相対的ですが、これはその時点では空のフィールドです。

インデックスページにすべてのレコードのリストを表示する場合にも同じ問題が発生します。距離と消費の列は空です。

その時点で距離を埋める最良の方法は何でしょうか?それとも、結局のところ、データベースに距離を保存する方が良いでしょうか?

これは私のインデックス関数です:

    [HttpGet]
    [Authorize]
    public ActionResult Index(string sortOrder, int? page)
    {
        ViewBag.CurrentSort = sortOrder;
        ViewBag.NameSortParm = String.IsNullOrEmpty(sortOrder) ? "asc" : "";

        List<Refuel> rf = db.Refuels.ToList();
        var refuels = from t in db.Refuels select t;

        switch (sortOrder)
        {
            case "asc":
                refuels = refuels.OrderBy(q => q.mileage);
                break;
            default:
                refuels = refuels.OrderByDescending(q => q.mileage);
                break;
        }

        // statistieken
        ViewBag.count = rf.Count();
        ViewBag.distance = rf.Sum(q => q.distance);
        ViewBag.volume = rf.Sum(q => q.volume);
        ViewBag.consumption = String.Format("{0:0.0}", rf.Where(q => q.consumption > 0).Average(q => q.consumption));
        ViewBag.consumption2 = String.Format("{0:0.0}", rf.Where(q => q.consumption2 > 0).Average(q => q.consumption2));
        ViewBag.cost = String.Format("{0:c2}", rf.Sum(q => q.totalPrice));

        int pageSize = 10;
        int pageNumber = (page ?? 1);
        return View(refuels.ToPagedList(pageNumber, pageSize));
    }

編集: 要約部分を修正することができました、もちろん、私は最後と最初のマイレージを使用して、走行距離の合計を取得することができました:

ViewBag.count = tb.Count();
ViewBag.distance = tb.Last().mileage - tb.First().mileage;
ViewBag.volume = tb.Sum(q => q.volume);
ViewBag.consumption = String.Format("{0:0.0}", ViewBag.volume / ViewBag.distance * 100);
ViewBag.consumption2 = String.Format("{0:0.0}", ViewBag.distance / ViewBag.volume);
ViewBag.cost = String.Format("{0:c2}", tb.Sum(q => q.totalPrice));

ここで行う必要があるのは、インデックステーブルのレコードごとの距離を表示することだけです。これは私のindex.cshtmlのループです:

@foreach (var item in Model)
{
    <tr>
        <td>
            @Html.ActionLink(Html.DisplayFor(modelItem => item.mileage).ToString(), "Details", new { id = item.id })
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.date)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.distance)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.volume)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.consumption)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.totalPrice)
        </td>
        <td>
            @Html.DisplayFor(modelItem => item.Gasstation.fullname)
        </td>
    </tr>
}
4

3 に答える 3

1

この場合も、距離を計算するために単一レコードの詳細ページで実行していることはすべて実行する必要があります。距離フィールドをデータベースに保存するよりも操作にコストがかかると思われる場合は、答えが得られます。

于 2012-12-28T14:54:30.373 に答える
0

ビュー自体で正しく計算できます。コレクションでforループを実行してレコードを表示し、最後の給油マイレージをi + 1またはi-1(ViewBag.CurrentSortに基づく)として取得し、そこで計算を実行するだけです。

編集 これはテストしていませんが、次のようになります。

コレクションの最初または最後のレコードの距離を計算するには、追加のレコードを返す必要があるため、並べ替え順序を受け入れるようにToPagedListメソッドを変更し、表示するレコードの前後に追加のアイテムを返す必要があります。

その場合、forループは次のようになります。

@{
    bool asc = ((string)ViewBag.CurrentSort).ToLower() == "asc";
    int i = 0;
    int records = Model.Count;

    //If sort is asc you want to skip the first record (the extra record you returned to do the calculation), else you want to stop before you get to the extra row at the end of the collection
    if (asc) i += 1;
    else records -= 1;

for (i; i<records; i++)
{
<tr>
    <td>
        @Html.ActionLink(Model[i].mileage.ToString(), "Details", new { id = Model[i].id })
    </td>
    <td>
        @Html.DisplayFor(modelItem => Model[i].date)
    </td>
    <td>
        @if (asc) {
        @Html.Display(Model[i].mileage - Model[i - 1].mileage)
        }
        else {
           @Html.Display(Model[i].mileage - Model[i + 1].mileage)
        }
etc...

そうは言っても、これはかなり基本的な機能であるべきもののための多くの作業のように感じます。そして、ビジネスロジックをビューから分離するというMVCの主要なポイントの1つから離れ始めています。

永続的な解決策は、距離をデータベースに保存することであるように見えます。給油テーブルに新しいレコードを追加するときは、最初に前のレコードを取得し、新しいレコードを追加するときに含める距離を計算する必要があります。追加するのは、単一のレコードを取得するための1つの追加呼び出しだけです。データベース操作は十分に安価であり、非常に大規模な違いしか見られません。しかし、それでも、上記のすべての作業はとにかくサーバー上で行われることになり、毎回それを繰り返すことはおそらくはるかに高価です。

于 2012-12-28T14:46:26.387 に答える
0

モデルにコンストラクターを作成し、距離を0に設定して、後でそれを埋めることを心配することができます。

于 2012-12-28T15:12:47.910 に答える