Kez*_*zer 14 asp.net-mvc linq-to-sql
我以前曾就这个话题问了几个问题.在我们能够在工作中实现MVC或LINQ之前,我们需要解决一些问题.
ASP.NET MVC中的多个记录集
使用的MVC的唯一示例仅返回单个结果集.当使用存储过程时,可以检索多个记录集,并且我们倾向于使用存储过程的全部原因有两个原因(我相信很多人也都知道).首先,如果我们需要传递参数,其次,如果我们想要返回多个数据表.在ASP.NET的MVC架构中,这怎么可能?
在本教程中,我们将了解如何检索数据.但是它使用ViewData.Model了表示单个结果集的内容,它没有解释如果返回多个结果集会发生什么,或者如何获取它们.
强类型存储过程输出
此外,ASP.NET网站上使用LINQ进行强类型输出解析的示例是通过使用*.dbml格式实现的,该格式是表模式的镜像,允许使用LINQ查找字段.大.但是,如果您的输出是从不直接映射到视图或表的存储过程自定义的,会发生什么?我们如何从这些存储过程中解析列名?
在上一节中,我描述了本教程,但这也只显示了如何仅为表创建LINQ to SQL,而不是从sproc创建自定义输出.
LINQ列查找
在工作中,我们运行一个宏,它将一堆类导出到我们的App_Code文件夹,因此存储过程参数是预定义的.这样做,所以我们不必调用DeriveParameters,它包含对数据库的额外调用.我们不希望这种情况发生,因为它有很多流量.如果我们使用LINQ,如何解析列数据类型?每当我们定义参数以找出参数的数据类型和名称时,是否有对数据库的调用?事情发生了变化吗?它是否仍然每次都调用DeriveParameters?这些缓存在某个地方吗?
DBML格式
*.dbml文件是否应包含数据库中的所有表?我们有大约15个数据库,每个数据库中有许多表.
每个输出的视图
还有一点要补充这篇文章.而不是手动创建dbml类最好将数据表示为视图,即使它是自定义输出?或者在dbml文件中创建自定义类是否更好?
这必须是最后一个问题,否则我会吃掉自己的手臂
"无法将'SingleResult`1 [IntranetMVC.UserDetail]'类型的对象强制转换为'IntranetMVC.UserDetail'."
这是功能:
Function Index() As ActionResult
ViewData("Message") = "Welcome to ASP.NET MVC!"
Dim userDetail As UserDetail
Dim office As IList(Of Office)
Dim activeUser As IList(Of ActiveUser)
Dim dept As IList(Of Department)
Using db As PersonnelDataContext = New PersonnelDataContext
Dim results As IMultipleResults = db.UserDetail(1168)
userDetail = results.GetResult(Of UserDetail)()
office = results.GetResult(Of Office)()
activeUser = results.GetResult(Of ActiveUser)()
dept = results.GetResult(Of Department)()
End Using
Return View(New IndexViewData(userDetail, office, activeUser, dept))
End Function
Run Code Online (Sandbox Code Playgroud)
它发生在所有userDetail, office, activeUser和dept任务上,但我不知道为什么.现在,我还没有正确地映射它们,但是以部门为例.我已经将表模式拖放到dbml文件中,因此它肯定存在并且格式正确.
UPDATE
这是我的实际代码.这不是最终的,我一直在玩它.似乎返回类型不对,但我不确定为什么.它似乎认为当存储过程实际返回四组数据时,只返回一个结果.其中一个集合只有一个结果,其他集合总是返回多个行:
无法转换'SingleResult 1[IntranetMVC.Office]' to type 'System.Collections.Generic.IList1 '类型的对象
Imports System.Data.Linq
Imports System.Reflection
Imports System.Data.Linq.Mapping
Partial Class PersonnelDataContext
<FunctionAttribute(Name:="dbo.UserDetailProc"), _
ResultType(GetType(UserDetail)), _
ResultType(GetType(IList(Of Office))), _
ResultType(GetType(IList(Of ActiveUser))), _
ResultType(GetType(IList(Of Department)))> _
Public Function UserDetail( _
<Parameter(Name:="User_Key", DbType:="Int")> ByVal User_Key As Integer, _
<Parameter(Name:="EditYN", DbType:="Char")> Optional ByVal EditYN As Char = "N") As IMultipleResults
Dim result As IExecuteResult = Me.ExecuteMethodCall(Me, CType(MethodInfo.GetCurrentMethod(), MethodInfo), User_Key, EditYN)
Return CType(result.ReturnValue, IMultipleResults)
End Function
End Class
Run Code Online (Sandbox Code Playgroud)
固定
好吧,我没有意识到,因为老实说,我没有正确检查返回类型.我假设结果.GetResult(Of MyType)(来自IMultipleResults)会返回一个集合.相反,它只返回单个结果并将指针移动到集合中的下一个项目.不幸的是,GetResult是唯一可以返回结果的公开方法,因此您必须遍历集合并将它们添加到通用列表中.
非常感谢!
Pur*_*ome 21
是的 - 最肯定的.
首先,您需要手动创建一个调用存储过程的方法,返回IMultipleResults结果.
此博客文章包含您需要的所有信息.它很简单,非常简单和有效.
你需要做的是两个步骤.
例如.
IndexViewData.cs
public class IndexViewData
{
IList<Customers> Customers { get; set; }
IList<Products> Products { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
.
HomeController.cs
public ActionResult Index()
{
IList<Customers> customers;
IList<Products> products;
// This grabs the multiple records from a single stored procedure.
// This code taken from the blog post link, above.
using (NorthwindDataContext db = new NorthwindDatacontext)
{
IMultipleResults results = db.GetMultipleRecordSets(arg1, ....);
customers = results.GetResult<Customer>();
products = results.GetProducts<Product>();
}
// Now return the view, with the viewdata that is required.
return View(new IndexViewData
{
Customers = customers,
Products = products
});
}
Run Code Online (Sandbox Code Playgroud)
.
Index.aspx
<%@ Page
Language="C#"
MasterPageFile="~/Views/Shared/Site.Master"
Inherits="System.Web.Mvc.ViewPage<IndexViewData>" %>
<% Html.RenderPartial("CustomersUserControl",
ViewData.Model.Customers); %>
<br/>
<h2>Products</h2>
<% foreach(var product in ViewData.Model.Products) { %>
Name: <%= product.Name %><br/>
<% } %>
...
Run Code Online (Sandbox Code Playgroud)
请注意,我没有做任何错误检查,等等.这是一个非常快速的pseduo代码指南,让你开始.
注意#2:请注意索引视图是强类型的(它继承了ViewPage.
我在上面回答了这个问题.请注意,您可以强烈键入您的ISingleResult存储过程.
好的,我想我明白你的意思,在这里.当您创建调用存储过程(一个ISingleResult或一个IMultipleResult)的方法时,您正在定义所需的参数,然后......将其视为硬编码.
当您将表拖放到linq到sql context gui canvas时,Visual Studio会在那里执行查找检查.然后,它在上下文的各种文件之一中创建类.例如.NorthwindDataContext.designer等.所以,这是一个一击的工作.创建类后,设计器会在画布上显示该类.有NO SYNC回数据库.没有.纳达.小人物.如果更改数据库模式中的任何内容(例如,添加新字段,更改存储过程参数等),datacontext将不会知道它.您需要删除该表并将其拖放回来.
如果在将表或存储过程拖放到画布上时运行SQL事件探查器,则可以看到Visual Studio"查询"数据库以获取信息.:)
是的.这是永远不会忘记的.一个一击的工作.需要手动同步.
HTH.
我注意到你又增加了两个q,所以我会在这里添加我的答案.
这是个人决定.15 DB!shees!这是一个公平的数字.无论如何,它归结为Context画布的可维护性.其次,每个上下文都创建它的OWN数据库连接.所以如果你的方法决定调用4个上下文,那么你有4个连接(和往返)到db,dude :)
就个人而言,我在Context Canvas上拥有所有表格.我从不在代码中使用这些表类.它们是私有的,仅用于我的Repository namespace/project/dll.我然后使用POCO课程来移动我所有的东西.这使我的代码更清晰,并且不依赖于存储库.
如果您已将存储的proc拖到linq上下文画布上,请将其删除.不需要引用该方法UserDetails(int userId).
现在,将以下代码(您需要将其转换为VB.NET)添加到数据上下文的部分类(我假设您知道这是什么/意味着什么,顺便说一句): -
[Function("UserDetails")] // <-- This is the name of your stored procedure.
[ResultType(TypeOf(UserDetail))]
[ResultType(TypeOf(Office))]
[ResultType(TypeOf(ActiveUser))]
[ResultType(TypeOf(Department))]
public IMultipleResults UserDetails(
[Parameter(Name = "UserId", DbType = "Int")] int userId)
// /\____ /\_____ ____/\
// This is where u _define_ the stored proc arguments.
{
IExecuteResult result = this.ExecuteMethodCall(this,
((MethodInfo)MethodInfo.GetCurrentMethod())), userId);
// This is where all the stored proc arguments are set ____/\
// This can be multiple args. eg. userId, name, ...
return (IMultipleResults)result.ReturnValue;
}
Run Code Online (Sandbox Code Playgroud)
然后就像你在以前的VB.NET代码中那样使用它.
问题(我猜)是你没有让方法处理IMultipleResults.您仍在使用旧的存储过程代码签名(默认情况下),它只是一个记录集结果(即.ISingleResult).
如果您将存储从服务器资源管理器拖放到linq Context Canvas上,则这是默认设置.
| 归档时间: |
|
| 查看次数: |
5723 次 |
| 最近记录: |