将旧版专有 Web 应用程序重写为 MVC3/Entity-Code-First
几个月来,我发布了一些有关 ASP.NET 应用程序和数据库抽象层结构的问题,目的是重写(从头开始)遗留 Web 应用程序。我最近偶然发现了 MVC3/Entity-Code-First,在花了一些时间使用它之后,我爱上了它的工作原理、事物的抽象方式,并且我正在寻找使用它的任何借口!
遗留应用程序是一个 C++/CLI Windows 服务,它生成自己的 HTML(非常老式的 HTML,CSS 仅用于颜色和大量表格),并且界面与业务逻辑紧密耦合。基本上,任何事情都会有所改善。
然而,也许这是因为我还没有在 MVC 上花费足够的时间,我有一些挥之不去的疑虑,并且想知道你们中的一些 MVC 专业人士是否可以向我传授他们的经验。
旧版应用程序使用自定义控件(它们自己的形式)将组合框绑定到数据,并根据另一个组合框中的选择动态重新填充依赖的组合框。在 ASP.NET 中,这个问题很容易回答,只需在页面上抛出一个
asp:DataList
控件,将其绑定到数据源即可。一些简单的代码允许您根据所选值过滤其他组合框。在 ASP.NET 中,实现另一个数据列表甚至以这种方式自动化依赖数据(这将很好地模仿遗留应用程序的行为)也很容易。我似乎在 MVC 中找不到自定义控件的概念,尽管我假设此类内容是通过 jQuery 调用来处理的,以获取数据并将其放入组合框中。但是,是否对每个页面上的每个组合框都执行了此操作?这是传递适当参数的部分视图的情况,还是这只是愚蠢的?我想这与实体框架的关系比 MVC 更多,但我在网上找到的大多数示例和教程都执行 LINQ 查询以返回要显示的对象集合,例如 MvcMovie 示例中的这个:
公共 ActionResult Index() { var movie = 来自 db.Movies 中的 m 其中 m.ReleaseDate >新的日期时间(1984, 6, 1) 选择米; 返回视图(电影.ToList()); }
然后在视图中使用
@foreach
循环进行渲染。这一切都很棒。遗留应用程序有一个浏览页面,可供系统的所有其他区域(超过 50 个)使用。它通过检查为登录用户定义的列顺序、展平任何外键(以便显示外表上的字段而不是非用户友好的主键值)来实现此目的,并且还允许用户应用自定义过滤器到任何列。对于行数超过 100k 的表也执行此操作。如何使用实体框架和视图编写类似的东西?在 ASP.NET 中,我可能会通过动态生成某种网格视图并让它自动生成列并应用过滤器来解决这个问题。这看起来我可能会在 MVC 方面做更多的工作。我错过了一些东西?旧应用程序有多个对大量数据进行操作的操作。现在因为它是一项服务,所以它可以启动这些线程而不必担心被关闭。我关于 SO 的问题之一是关于静态管理器的存在以及 AppPool 回收的引入,但我认为拥有辅助服务是一个不错的选择。也就是说,旧应用程序将更新语句应用于大量记录而不是单行。实体框架是否可以实现这一点,而无需针对绕过正常模型的数据库编写自定义 SQL?我希望我不必做这样的事情(不是我愿意,这只是举例)
var 记录 = 来自 myTable 中的记录 其中 someField = someValue 选择记录; foreach(记录中的记录) rec.applyCalculation(); db.SaveDbChanges();
我怀疑这可能需要很多时间,而旧版应用程序只需这样做:
更新 myTable 设置字段 1 = 计算 其中 someField = someValue
所以我并不完全清楚我们如何以这种方式使用我们的模型。
旧版应用程序的布局中有一些数据面板,无论您所在的页面如何,这些数据面板都会随处可见。在 Stackoverflow 上查看,我发现这个问题,这意味着< em>每个视图都需要将此信息传递给布局?是这样吗,还是有更好的办法?理想情况下,我希望我的布局能够访问特定模型/存储库并在侧面板中显示数据。添加到每个视图页面可能会非常重复并且容易出错。更不用说如果我需要修改某些东西会花费时间。此处可以使用部分视图,但我再次不确定如何在布局页面上将模型传递给它。
最后,在安装 Ef-Code-First 后,我很失望地发现一个非常好的属性
SourceName
还没有出现。这在映射遗留表/列时非常好,我不完全确定为什么此时它被排除在外(至少,我的智能感知说它不存在!)有谁知道什么时候会发生这种情况?我可以暂时不用它,但最终它会非常有用。
抱歉问了这么长的问题。经过对 ASP.NET 和 MVC3 多年的研究工作,我真的很想使用 MVC3!
I've posted a few questions over the months about structure of ASP.NET applications and Database-Abstraction-Layers, for the purposes of rewriting (from the ground-up), a legacy web application. I've recently stumbled on MVC3/Entity-Code-First and after spending some time with it, have fallen in love with how it works, how things are abstracted out, and I'm looking for any excuse to use it!
The legacy application is a C++/CLI windows service that generates it's own HTML (very old-school HTML at that with CSS just used for colours, and tables-abound), and with interface very tightly coupled to business-logic. Basically, anything is going to be an improvement.
However, and perhaps this is because I have not spent enough time yet with MVC, I have a few nagging doubts and wondered if some of you MVC-Pros could waft their experience in my direction.
The legacy app uses custom controls (it's own form of them) to bind combo-boxes to data, and dynamically repopulate dependent combo-boxes based on selections in another. In ASP.NET, this question is answered easily as one just throws an
asp:DataList
control on the page, binds it to a data source and voila. A bit of simple code allows you to then filter other combo boxes on the selected value. It also would be easy in ASP.NET, to implement another data-list that even automated dependent data in this fashion (which would mimic the behavior of the legacy app quite nicely). I can't seem to find a notion of custom controls in MVC, though I assume this kind of stuff is handled by jQuery calls to get data and throw it in to a combo box. But is this done for every combo-box on every page that has one? Is this a case for partial views with appropriate parameters being passed, or this just stupid?I guess this relates more to the Entity Framework than MVC, but most of the examples I've found on the web, and tutorials, perform LINQ queries to return a collection of objects to display, e.g this, from the MvcMovie example:
public ActionResult Index() { var movies = from m in db.Movies where m.ReleaseDate > new DateTime(1984, 6, 1) select m; return View(movies.ToList()); }
Which is then rendered using a
@foreach
loop in the view. This is all great. The legacy application has a single browse page that is used by all the other areas of the system (there are over 50). It does this by inspecting the column order defined for the user logged on, flattening any foreign keys (so that the field on the foreign table is displayed as opposed to the non-user-friendly primary key value) and also allows the user to apply custom filters to any column. It does this also for tables that have upward of 100k rows. How would one go about writing something similar using the Entity-framework and views? In ASP.NET I'd probably solve this by dynamically generating a grid view of some sort and have it auto-generate the columns and apply the filters. This seems like it might me more work in MVC. I am missing something?The legacy application has several operations that operate over large sets of data. Now because it was a service, it could launch these threads without worrying about being shut-down. One of my questions here on SO was about static managers being around and the introduction of an AppPool recycle, but I have decided that having an auxiliary service is a good option. That said, the legacy app applies an update statement to large groups of records rather than single rows. Is this possible with Entity-Framework without writing custom SQL against the database that bypasses the normal models? I hope I don't have to do something like this (not that I would, this is just for example)
var records = from rec in myTable where someField = someValue select rec; foreach(rec in records) rec.applyCalculation(); db.SaveDbChanges();
I suspect this could take a lot of time, whereas the legacy app would just do:
UPDATE myTable SET field1 = calc WHERE someField = someValue
So it's not entirely clear to me how we use our models in this manner.
The legacy application has some data panels in the layout that get carried around whatever page you're on. Looking here on Stackoverflow, I found this question, which implies that every view needs to pass this information to the layout? Is this so, or is there a better way? Ideally, I'd like my layout to be able to access a particular model/repository and display the data in a side-panel. Adding to every view page could be quite repetitive and prone to error. Not to mention the time it would take if I needed to modify something. A partial view would do here, but again I am unsure how to pass a model to it on the layout page.
Finally, I was disappointed, after installing Ef-Code-First, to find that a really nice attribute,
SourceName
has not made it in, yet. This would be very nice in mapping against legacy tables/columns and I am not entirely sure why it has been left out at this point (at least, my intellisense says it's not there!) Has anyone got an idea when this might come about? I could do without it for a while, but ultimately it would be incredibly useful.
Sorry for the lengthy questions. After ages of investigative work in ASP.NET and MVC3, I really want to go with MVC3!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
如果我设法正确提取问题,那么这将是我的答复:
您对主 - 详细信息下拉列表(或其他控件)的思考是正确的。 jQuery AJAX/JSON 调用(主要是 GET)将是您所需要的。如果您的页面上只有一个下拉菜单,那么您当然不需要这种交互性 - 您只需在控制器操作中为其准备模型(创建一个 SelectList 对象)。
在这里,您很可能最终会使用某种网格系统,例如 jqGrid 或 Flexigrid。他们自己完成了大部分有关过滤/搜索/查询的工作。不过,您仍然必须提供将提供数据的 JSON 控制器操作。
是的,您可以通过 EF 执行 SQL。有
ExecuteStoreQuery()
和ExecuteStoreCommand()
。以下是有关这些内容的更多信息 http://msdn.microsoft.com/en-us/library /ee358769.aspx您可以从视图中调用 RenderAction() 并让此操作按需准备数据(无论何时调用)并渲染出部分(或正常) )查看并向其提供数据(模型)。
RenderPartial()
对此有点笨拙 - 它要求您在调用RenderPartial()
的视图中已有可用的模型。RenderPartial()
永远不会返回到控制器操作 - 它只是使用您在视图中的调用中提供的模型渲染模板中定义的 HTML。不幸的是我不知道这个问题的答案。
华泰
If I managed to extract the questions correctly then this would be my reply:
You are right in your thinking about master - detail dropdowns (or other controls, for that matter). jQuery AJAX/JSON calls (mostly GETs) will be what you need. If you only have one dropdown on your page, then of course you don't need that kind of interactivity - you can just prepare the model for it in your controller action (you create a SelectList object).
Here you would most likely end up using some kind of a grid system like jqGrid or Flexigrid. They do most of the stuff regarding filtering/searching/querying themselves. Still you will have to provide JSON controller actions that will be serving data.
Yes you can execute SQL via EF. There's
ExecuteStoreQuery()
andExecuteStoreCommand()
. Here's more on those http://msdn.microsoft.com/en-us/library/ee358769.aspxYou can call
RenderAction()
from the view and have this action prepare the data on demand (whenever you call it) and render out the Partial (or normal) view and feed the data (model) to it.RenderPartial()
is a bit more clumsy with this - it requires you to have the model already available in the view in which you are callingRenderPartial()
.RenderPartial()
never goes back to the controller action - it just renders out that HTML defined in the template using the model you provided in its call from within the view.Unfortunately I don't know the answer to this.
HTH
您可能不喜欢它,但重构 C++ 应用程序可能更有意义。尤其是对于企业来说。生成html没有任何问题。重构现代 html/css 比一组模板容易得多。
You might not like it, but it could make a lot more sense to just refactor the c++ application. Especially to the business. There's nothing wrong with generating html. Much easier to refactor to modern html/css than a set of templates.