EF Core 存储过程返回结果不同

问题描述 投票:0回答:3

我有这个存储过程

CREATE PROCEDURE [dbo].[GetBooksByAuthor2]
AS
    SELECT 
        books.Id, authors.Name AS Author, books.Name AS Book 
    FROM
        dbo.Authors authors
    INNER JOIN 
        dbo.AuthorsBooks authorsBooks ON authors.Id = authorsBooks.AuthorId
    INNER JOIN 
        dbo.Books books ON books.Id = authorsBooks.BookId
GO

在 SQL Server Management Studio 中,结果如下所示:

Id| Author       | Book
--+--------------+----------
1 | FirstAuthor  | GoodBook1
2 | FirstAuthor  | GoodBook2
3 | FirstAuthor  | GoodBook3
1 | SecondAuthor | GoodBook1
3 | SecondAuthor | GoodBook3 

在 EF Core 中,我为存储过程添加了视图模型

public class BookViewModel
{
    [Key]
    public int Id { get; set; }

    public string Author { get; set; }
    public string Book { get; set; }
}

我还在上下文类中添加了类似的内容:

public partial class StrangeContext : DbContext
{
     public virtual DbSet<BookViewModel> Books2 { get; set; }
}

然后我在控制器操作中调用它

[HttpGet]
public JsonResult GetAuthors()
{
    var result = db.Books2.FromSql("GetBooksByAuthor2").ToList();
    return new JsonResult(result);
}

Json 的结果看起来像

[
    { "id": 1, "author":"FirstAuthor", "book":"GoodBook1"},
    { "id": 2, "author":"FirstAuthor", "book":"GoodBook2"},
    { "id": 3, "author":"FirstAuthor", "book":"GoodBook3"}, 
    { "id": 1, "author":"FirstAuthor", "book":"GoodBook1"}, 
    { "id": 3, "author":"FirstAuthor", "book":"GoodBook3"}
]

我做错了什么?错误的视图模型?第二作者在哪里?

c# entity-framework-core
3个回答
5
投票

您将

Id
BookViewModel
定义为 Key,因此,实体框架在第一次使用
1
Id 查询“FirstAuthor”时会进行缓存。第二次遇到
Id
1 时,它使用当前上下文并根据缓存的值填充实体。

这里的问题是你的模棱两可的模型。

FirstAuthor
SecondAuthor
怎样才能同时具有
Id
= 1.

您可以删除模型中的 Key 属性,但这可能会导致混乱,无论您在何处显示这些结果,一旦您想要保存任何这些实体,您都会得到不可预测的结果。

您也可以尝试

AsNotracking()
,但我强烈建议您不要这样做,因为一旦您尝试跟踪或保存更改,您就会遇到麻烦。相反,调整您的存储过程以返回唯一行的唯一 ID。


2
投票

您已在

Id
类中将
BookViewModel
定义为键,但传递了非唯一值:

authorsBooks.Id
添加到您的 SQL 查询并将其传递给您类中的
[Key]
,并定义另一个字段以在您的查询和类中显示
BookId

代码如下:

public class BookViewModel
{
    [Key]
    public int Id { get; set; }

    public string Author { get; set; }

    public int BookId { get; set; }

    public string Book { get; set; }
}

你最好这样写你的程序:

ALTER PROCEDURE [dbo].[GetBooksByAuthor2]
AS
    SELECT 
        AB.Id AS id, B.Id AS bookId, 
        A.[Name] AS author, B.[Name] AS book 
    FROM
        dbo.AuthorsBooks AS AB
    INNER JOIN 
        dbo.Books B ON AB.BookId = B.Id
    INNER JOIN 
        dbo.Authors A ON A.Id = AB.AuthorId
GO

1
投票

由于 Sp 返回有多个具有相同 Id 的条目。 在上面给定的表实体的 DbContext 注册中使用 DbQuery,而不是使用 DbSet。使用就会得到数据。 注意:DbQuery 不支持 key,因为任何属性都会删除 Id 的 key 属性。

© www.soinside.com 2019 - 2024. All rights reserved.