我有这个存储过程
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"}
]
我做错了什么?错误的视图模型?第二作者在哪里?
您将
Id
的 BookViewModel
定义为 Key,因此,实体框架在第一次使用 1的
Id
查询“FirstAuthor”时会进行缓存。第二次遇到 Id
1 时,它使用当前上下文并根据缓存的值填充实体。
这里的问题是你的模棱两可的模型。
FirstAuthor
和 SecondAuthor
怎样才能同时具有 Id
= 1.
您可以删除模型中的 Key 属性,但这可能会导致混乱,无论您在何处显示这些结果,一旦您想要保存任何这些实体,您都会得到不可预测的结果。
您也可以尝试
AsNotracking()
,但我强烈建议您不要这样做,因为一旦您尝试跟踪或保存更改,您就会遇到麻烦。相反,调整您的存储过程以返回唯一行的唯一 ID。
您已在
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
由于 Sp 返回有多个具有相同 Id 的条目。 在上面给定的表实体的 DbContext 注册中使用 DbQuery,而不是使用 DbSet。使用就会得到数据。 注意:DbQuery 不支持 key,因为任何属性都会删除 Id 的 key 属性。