如何在MVC中传递模型,以便我不必两次查询数据库?

时间:2012-09-16 22:42:57

标签: asp.net asp.net-mvc razor

我想在我的页面上创建一个导出模型的超链接,但我不想为每个需要导出的模型编写方法。我想最终得到一个方法,可以将模型作为其中一个参数并在该模型上执行导出逻辑。 有没有办法可以将我发送到视图的模型传递回控制器操作?

修改

我有以下控制器操作 -

    public ViewResult PenDaily(Nullable<DateTime> startDate = null, Nullable<DateTime> endDate = null, string listName = "")
    {
        //Removed code for brevity/clarity

        PenDailyViewModel penDailyView = new PenDailyViewModel();
        penDailyView.startDate = startDate;
        penDailyView.endDate = endDate;
        penDailyView.listNames = GetLists(m_db);
        penDailyView.penDaily = GeneratePenDaily(m_db, listName, startDate, endDate);
        penDailyView.penSummary = GeneratePenSummary(m_db, startDate, endDate, "").Where(a => a.listName == listName);

        return View(penDailyView);
    }

PenDailyViewModel是我传递给Razor View的模型对象。 PenDaily和PenSummary都是IQueryable对象,在结果页面的表中使用。 PenDaily是主要的数据集,PenSummary用于表格页脚中的总行。

我想获取这组数据并将其导出到文件中。我有一个函数编写,但我不知道如何从我的页面使用它。我想进行设置,以便当用户点击超链接时,系统会提示他们保存导出。

如果有帮助,我的剃刀观点:

@model WebTools.Models.PenDailyViewModel

<table>
    <thead>Header Stuff</thead>
    <tbody>
    @foreach (var item in Model.penDaily)
    {
        //Generate table body
    }
    </tbody>
    <tfoot>
    @foreach (var item in Model.penSummary)
    {
        //Generate table footer
    }
    </tfoot>
</table>

2 个答案:

答案 0 :(得分:1)

就个人而言,我总是为视图创建单独的模型(即。GET)或任何POSTS

  • IndexViewModel
  • IndexInputModel
很多时候,这些poco非常相似。

现在的诀窍可能是利用AutoMapper,这样您就可以更轻松地支持/维护代码,而不是拥有大量从左到右的代码(例如.foo = viewmodel.Foo)。 / p>

这个想法是这样的:你有一个在控制器中使用的基类库对象。它是主要的POCO对象。接下来,您可以看到与此POCO的架构/结构直接相关的视图模型和输入模型。使用AutoMapper(或许多从左到右的代码,如果你还是这个编程的新手),你可以轻松地“复制”相关对象之间的数据。

例如

示例视图。

视图模型。

public class IndexViewModel
{
    public string Name { get; set; }
    public string Description { get; set; }
    public Uri InfoUrl { get; set; }
}

(查看)动作方法(错误检查等等......剥离)。

// product/{id}   eg /products/5
public Action Index()
{
    // Load the Product.
    var product = YourRepository.Load(id);
    if (product == null)
    {
        return NotFound("Product can't be found.");
    }

    // Convert the product to this view requirements.
    // This will copy over the Name and the Uri.
    var model = Mapper.Map<Product, IndexViewModel>(product);

    return View(model);
}

这里的命令式是什么,该ONE视图的模型有一个 - 硬 - 清晰的表示。每个视图都应该有自己的模型,因为每个视图都是唯一的。

现在你可能会说'我不想要两个型号'。好吧,我建议你这样做。事实上,这里有3个型号。控制器/服务/业务逻辑的主要部分。另外两个用于输入(可选)或视图(每个动作都需要某种类型的结果)。

更新

你说你想避免多次访问数据库。公平的电话! :)诀窍是改用CACHING。不将数据存储在客户端中?为什么?首先,我可以在1秒内破解客户端数据。第二个缓存(通常)便宜且(通常)非常快。

让我们更新初始代码......

// product/{id}   eg /products/5
public Action Index()
{
    // Load the Product from your cache
    var product = YourCache.Load(id);
    if (product == null)
    {
        return NotFound("Product can't be found.");
    }

    // Convert the product to this view requirements.
    // This will copy over the Name and the Uri.
    var model = Mapper.Map<Product, IndexViewModel>(product);

    return View(model);
}

..这里有一些示例Cache pseduo-code ..

public class YourCache
{
    private static ObjectCache cache = MemoryCache.Default; 

    private IRepository Repository { get; set; }

    public YourCache(IRepository repository)
    {
        Repository = repository;
    }

    public Product Load(int id)
    {
        var product = cache["Product-" + id] as Product;
        if (product == null)
        {
            // Grab it and remember it.
            product = repository.Load(id);

            if (product != null)
            {
                cache.Set("Product-" + id, product, ....);
            }
        }

        return product;
    }
}

答案 1 :(得分:0)

将要返回的数据传递到隐藏的表单字段中,然后使用表单而不是简单的超链接将回调发送回控制器。然后它将从隐藏字段接收数据。

这是一个真正的页面状态,而不是可能与页面状态不同步的会话状态(使用后退按钮,打开另一个选项卡/窗口等)。

也就是说,如果查询价格便宜(因此速度很快),那么访问数据库并不一定是件坏事。