如何在实体框架中调用带有联接的存储过程?

Posted

技术标签:

【中文标题】如何在实体框架中调用带有联接的存储过程?【英文标题】:How to call Stored Procedure with Joins in Entity framework? 【发布时间】:2021-07-07 09:38:11 【问题描述】:

.Net Core 3.1

这是我的tables

我不允许在其中添加任何外键或新关系。我创建了一个将其他 3 个表连接到 Ordering_Policy 表的存储过程。

create procedure spOrderingPolicy
as
    select op.Id, op.Tyre_Grade, op.Tyre_Group, tb.Tyre_Brand, ss.Status, tc.Cosmetic
    from [dbo].[Ordering_Policy] as op

    left join [dbo].[Tyre_Brand] as tb
    on op.Tyre_Brand_Id = tb.Id
    left join [dbo].[Shearography_Status] as ss
    on op.Shearography_Id = ss.Id
    left join [dbo].[Tyre_Cosmetic] as tc
    on op.Cosmetic_Id = tc.Id
go

结果result符合预期:

所以我尝试调用该过程:

public IEnumerable<OrderingPolicy> GetOrder()

    using (Ordering_PolicyContext context = new Ordering_PolicyContext())
    
        var order = context.OrderingPolicies.FromSqlRaw<OrderingPolicy>("spOrderingPolicy").ToList();
        return order;
    

但它会忽略任何不在 Ordering_Policy 中的内容:result

如何调用过程并像查询一样显示所有数据?

编辑:这是 OrderingPolicy 的类

namespace Ordering_Policy.Models

    public partial class OrderingPolicy
    
        public int Id  get; set; 
        public string TyreGrade  get; set; 
        public int? TyreGroup  get; set; 
        public int? ShearographyId  get; set; 
        public string CasingLife  get; set; 
        public string Variance  get; set; 
        public string ColorCode  get; set; 
        public string Injury  get; set; 
        public int? MaxCrownPatch  get; set; 
        public int? MaxShoulder  get; set; 
        public int? Age  get; set; 
        public int? CosmeticId  get; set; 
        public int? TyreBrandId  get; set; 
    

【问题讨论】:

您的“订单”列表中有什么?你在这个变量中有你需要的数据吗? 请不要在有文字的地方使用图片。此外,我们看不到 OrderingPolicy 类。 你能告诉你 OrderingPolicie 类吗? 【参考方案1】:

您需要创建一个与存储过程返回的结果集匹配的Keyless Entity Type,并在该 DbSet 上调用 OrderingPolicyEx.FromSqlRaw 而不是 OrderingPolicy

【讨论】:

【参考方案2】:

你应该使用INNER Join而不是left Join:

这是我的演示,带有你的实体类(有点简化):

CREATE PROCEDURE [dbo].[spOrderingPolicy]  
as

select op.Id, op.TyreGrade, 
op.TyreGroup,op.CosmeticId,op.ShearographyId,op.TyreBrandId, tb.Brand, ss.status, 
tc.cosmetic
from dbo.OrderingPolicy as op

INNER JOIN [dbo].[Tyre_Brand] as tb
on op.TyreBrandId = tb.Id
INNER JOIN [dbo].[Shearography_Status] as ss
on op.ShearographyId = ss.Id
INNER JOIN [dbo].[Tyre_Cosmetic] as tc
on op.CosmeticId = tc.Id
Go

结果:只显示匹配的行

【讨论】:

【参考方案3】:

我终于找到了解决方案:创建新的类和上下文,只为调用存储过程中的列

类:

public partial class Tyre_Detail

    public int? Id  get; set; 
    public string Tyre_Grade  get; set; 
    public int? Tyre_Group  get; set; 
    public string Tyre_Brand  get; set; 
    public string Status  get; set; 
    public string Cosmetic  get; set; 

数据必须具有与存储过程中的列完全相同的名称。这个类中没有键,所以数据类型,在这种情况下是int 需要有问号。

然后为类创建上下文文件:

modelBuilder.Entity<Tyre_Detail>(entity =>

     entity.HasNoKey();

     entity.Property(e => e.Id);
     entity.Property(e => e.Tyre_Grade);
     entity.Property(e => e.Tyre_Group);
     entity.Property(e => e.Tyre_Brand);
     entity.Property(e => e.Status);
     entity.Property(e => e.Cosmetic);
     );

由于这是无密钥实体,.HasNoKey() 是必不可少的。

【讨论】:

以上是关于如何在实体框架中调用带有联接的存储过程?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用实体框架在 oracle 包中调用存储过程?

实体框架和 Oracle 客户端 - 存储过程问题

使用带有 C# 的 Entity Framework 6 调用现有的存储过程

使用带有 OData 提要 C# 的存储过程的自定义分页,没有实体框架

带有存储过程的实体框架 VS LINQ to SQL VS ADO.NET? [关闭]

VS 2010 - 带有 MySql 存储过程的实体框架似乎不起作用