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