如果使用LINQ to SP和Sp返回多个记录集,则DBML中缺少模式

时间:2010-12-29 12:35:21

标签: linq linq-to-sql linq-to-entities

在制作LINQ to SQL和实体的POC的同时,我遇到了陷入僵局的问题。 问题是,我正在使用LINQ to SP,并且每件事情都运行正常,我制作了很酷的编辑,添加和删除方法。然后有些东西点击我的我的“如果我只从SP返回两个记录集怎么办”。我制作了一个SP并从中返回了两个记录集

SP看起来像这样[演示]

Create PROCEDURE [dbo].GetUserData

    @UserId Bigint

AS
BEGIN
    SET NOCOUNT ON;

-- Getting User
select * from [User] where id=@UserId
-- Getting User's role
select * from [Role] where userId=@UserId
end

然后我在我的DBML(Linq to SQL类)中删除了那个SP然后在这里我注意到只创建了一个记录集的模式

<?xml version="1.0" encoding="utf-8"?>
<Database Name="MyInventory" Class="MyDBMLDataContext" xmlns="http://schemas.microsoft.com/linqtosql/dbml/2007">
  <Connection Mode="AppSettings" ConnectionString="Data Source=MyDatabaseServer\;Initial Catalog=MyInventory;Integrated Security=True" SettingsObjectName="ConsoleApplication16.Properties.Settings" SettingsPropertyName="MyInventoryConnectionString" Provider="System.Data.SqlClient" />
  <Function Name="dbo.GetUserData" Method="GetUserData">
    <Parameter Name="UserId" Parameter="userId" Type="System.Int64" DbType="BigInt" />
    <ElementType Name="GetUserDataResult">
      <Column Name="Id" Type="System.Int64" DbType="BigInt NOT NULL" CanBeNull="false" />
      <Column Name="Name" Type="System.String" DbType="VarChar(50) NOT NULL" CanBeNull="false" />
      <Column Name="Email" Type="System.String" DbType="NVarChar(50)" CanBeNull="true" />
      <Column Name="IsDeleted" Type="System.Boolean" DbType="Bit NOT NULL" CanBeNull="false" />
      <Column Name="HomePage" Type="System.String" DbType="VarChar(100)" CanBeNull="true" />
    </ElementType>
  </Function>
</Database>

我可以清楚地看到,只有一个记录集是由用户记录创建的,并且缺少角色架构:(。

任何人都可以告诉我这是什么以及为什么会这样?

由于 Lura公司

3 个答案:

答案 0 :(得分:2)

在从网站的数据库中获取多个数据集时,我不得不处理类似的事情。我们所做的是创建一个DatabaseExtensions.cs文件,以添加具有多个数据集的查询。

所以在扩展文件中我们会有这样的东西

public partial class DataBaseDataContext
{
    [ResultType(typeof(FirstResult))]
    [ResultType(typeof(SecondResult))]
    [Function(Name = "dbo.StoredProc")]
    public IMultipleResults StoredProc([global::System.Data.Linq.Mapping.ParameterAttribute(DbType = "Int")] System.Nullable<System.Int> ID)
    {
        IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())), ID);
        return ((IMultipleResults)(result.ReturnValue));
    }
}

public class FirstResult;

public class SecondResult;

注意:我更改了此代码中的一些名称,以便于阅读,因此可能无法正常工作。

FirstResult和SecondResult是结果类型类。我通常会从dbml附带的.cs文件中复制它们,然后重命名它。我没有在这里包含他们的代码,因为它可能会很长。

DataBaseDataContext dataCon = new DataBaseDataContext();
var results = dataCon.StoredProc(id);
var firstSet = results.GetResult<FirstResult>();
var secondSet = results.GetResult<SecondResult>();
//process data

以与存储过程中出现的顺序相同的顺序获取结果非常重要。在得到结果后,您可以使用LINQ或其他任何方法来处理它们。

答案 1 :(得分:0)

您是否看过为您的模型生成的代码?两个结果集将在这里。映射可能存在。

拉​​梅什

答案 2 :(得分:0)

我的发现是,如果您手动将结果集添加到dbml,您将获得所需的结果,但LinqToSql不会为您提供访问它们的简单方法

以下是结果的路径

((System.Data.Linq.SqlClient.ObjectReaderCompiler.ObjectReaderSession
    <System.Data.SqlClient.SqlDataReader>)
   (((System.Data.Linq.SqlClient.SqlProvider.ExecuteResult)(result)).session)).buffer

您可以通过索引buffer[0]访问结果,并返回第一个选择语句的结果,buffer[1]返回第二个选择的结果。 可能你可以将这两个IEnumerable转换为IEnumerable<GetAllResult>IEnumerable<GetAllResult1>,但我没有测试过。

我构建了这个示例dbml

<Function Name="dbo.GetAll" Method="GetAll">
    <ElementType Name="GetAllResult">
      <Column Name="ID" Type="System.Int32" DbType="Int" CanBeNull="true" />
      <Column Name="Tagname" Type="System.String" DbType="NChar(10)" CanBeNull="true" />
    </ElementType>
    <ElementType Name="GetAllResult1">
      <Column Name="Id" Type="System.Int32" DbType="Int" CanBeNull="true" />
      <Column Name="TagId" Type="System.Int32" DbType="Int" CanBeNull="true" />
      <Column Name="Name1" Type="System.String" DbType="NChar(10)" CanBeNull="true" />
    </ElementType>
  </Function>

生成的cs文件就像这样

[global::System.Data.Linq.Mapping.FunctionAttribute(Name="dbo.GetAll")]
[global::System.Data.Linq.Mapping.ResultTypeAttribute(typeof(GetAllResult))]
[global::System.Data.Linq.Mapping.ResultTypeAttribute(typeof(GetAllResult1))]
public IMultipleResults GetAll()
{
   IExecuteResult result = this.ExecuteMethodCall(this, ((MethodInfo)(MethodInfo.GetCurrentMethod())));
   return ((IMultipleResults)(result.ReturnValue));
}