C# 如何在没有一个相关实体的情况下获得一对一对象?

C# 如何在没有一个相关实体的情况下获得一对一对象?,c#,asp.net,.net,asp.net-mvc,entity-framework,C#,Asp.net,.net,Asp.net Mvc,Entity Framework,我有一个Book类,它包含一个InventoryItem,InventoryItem包含这本书,所以关系是一对一的。如果我想获取库存项目,它将返回包含该库存项目的书籍,依此类推。我想将该InventoryItem作为IActionResult返回。 图书类: public string Title { get; set; } public IEnumerable<Author> Authors { get; set; } public Category Category { get;

我有一个Book类,它包含一个InventoryItem,InventoryItem包含这本书,所以关系是一对一的。如果我想获取库存项目,它将返回包含该库存项目的书籍,依此类推。我想将该InventoryItem作为IActionResult返回。

图书类:

public string Title { get; set; }
public IEnumerable<Author> Authors { get; set; }
public Category Category { get; set; }
public string Isbn { get; set; }
public string PublishingHouse { get; set; }
public string Edition { get; set; }
public InventoryItem InventoryItem { get; set; }
public bool IsDamaged { get; set; }
public bool IsLost { get; set; }
public Guid BookId { get; set; }
public Book Book { get; set; }
public int Number { get; set; }
public AcquisitionDetail AcquisitionDetail { get; set; }
public async Task<IEnumerable<InventoryItem>> GetInventoryItemsAsync()
{
    return await schoolLibraryContext.InventoryItems.Include(inventoryItem => inventoryItem.Book)
        .Include(inventoryItem => inventoryItem.AcquisitionDetail)
        .ToListAsync();
}
返回InventoryItem的方法:

public string Title { get; set; }
public IEnumerable<Author> Authors { get; set; }
public Category Category { get; set; }
public string Isbn { get; set; }
public string PublishingHouse { get; set; }
public string Edition { get; set; }
public InventoryItem InventoryItem { get; set; }
public bool IsDamaged { get; set; }
public bool IsLost { get; set; }
public Guid BookId { get; set; }
public Book Book { get; set; }
public int Number { get; set; }
public AcquisitionDetail AcquisitionDetail { get; set; }
public async Task<IEnumerable<InventoryItem>> GetInventoryItemsAsync()
{
    return await schoolLibraryContext.InventoryItems.Include(inventoryItem => inventoryItem.Book)
        .Include(inventoryItem => inventoryItem.AcquisitionDetail)
        .ToListAsync();
}
公共异步任务GetInventoryItemsAsync() { return wait schoolLibraryContext.InventoryItems.Include(inventoryItem=>inventoryItem.Book) .Include(inventoryItem=>inventoryItem.AcquisitionDetail) .ToListAsync(); }
问题:当我想要返回InventoryItem时,如何只包含一个没有InventoryItem的Book对象。

我假设问题是关于实体框架的,因为它在标记中

在应用程序中使用数据方面:

public string Title { get; set; }
public IEnumerable<Author> Authors { get; set; }
public Category Category { get; set; }
public string Isbn { get; set; }
public string PublishingHouse { get; set; }
public string Edition { get; set; }
public InventoryItem InventoryItem { get; set; }
public bool IsDamaged { get; set; }
public bool IsLost { get; set; }
public Guid BookId { get; set; }
public Book Book { get; set; }
public int Number { get; set; }
public AcquisitionDetail AcquisitionDetail { get; set; }
public async Task<IEnumerable<InventoryItem>> GetInventoryItemsAsync()
{
    return await schoolLibraryContext.InventoryItems.Include(inventoryItem => inventoryItem.Book)
        .Include(inventoryItem => inventoryItem.AcquisitionDetail)
        .ToListAsync();
}
在这种情况下,你真的不用担心它。除非您使用
Include
专门询问它,
Book
将被延迟加载,也就是说,它不会在初始查询中发送,如果您实际使用它,将发送另一个查询来检索它

不过要小心,延迟加载可以节省大量通信量,但它也很容易导致“N+1”问题,即即使您可以一次加载整个实体,也会不断发送查询。因此,如果您稍后实际使用了
Book
,最好使用
Include
并在最初加载,与数据流量相比,执行查询的成本相对较高

关于将此数据发送到外部(通过API)

永远不要将您的实体返回到外部。即使您真的想要返回它的所有属性,这也是一种非常糟糕的做法

如果在外部返回数据,则应将其映射到其他类的对象,然后返回该类。通过这种方式,您可以确保永远不会发送太多数据,例如,使用不想发送到外部的属性扩展实体

在您的情况下,它可能看起来像:

public class BookModel
{
    public string Title { get; set; }
    public IEnumerable<AuthorModel> Authors { get; set; }
    public Category Category { get; set; }
    public string Isbn { get; set; }
    public string PublishingHouse { get; set; }
    public string Edition { get; set; }
    public bool IsDamaged { get; set; }
    public bool IsLost { get; set; }
}

public class InventoryItemModel
{
    public Guid BookId { get; set; }
    public BookModel Book { get; set; }
    public int Number { get; set; }
    public AcquisitionDetailModel AcquisitionDetail { get; set; }
}
公共类图书模型
{
公共字符串标题{get;set;}
公共IEnumerable作者{get;set;}
公共类别{get;set;}
公共字符串Isbn{get;set;}
公共字符串发布库{get;set;}
公共字符串版本{get;set;}
公共布尔已损坏{get;set;}
公共bool IsLost{get;set;}
}
公共类InventoryItemModel
{
公共Guid BookId{get;set;}
PublicBookModelBook{get;set;}
公共整数{get;set;}
公共AcquisitionDetailModel AcquisitionDetail{get;set;}
}

如果您使用此函数通过API返回,您可以创建ViewModel并使用AutoMapper映射要显示的属性?好的,谢谢您的回答。但是如果我使用延迟加载,我需要使对象属性虚拟,不是吗?我还尝试将实体映射到模型,但不起作用,我得到了相同的对象,但在模型中。也许,我不明白什么。看看我答案中的片段。将实体映射到模型的原因之一是删除导航属性中的循环。在这种情况下,
InventoryItemModel
包含对
BookModel
的引用,但是
BookModel
不再包含对
InventoryItemModel
的引用,因此如果您在通过API发送之前将实体映射到此模型,您将只获得一本书的副本,而不是这个无休止的循环。是的,如果您想使用延迟加载,属性应该是虚拟的。从上下文中获取实体后,立即将其映射到Model/DTO(数据传输对象,在大多数情况下,它与实体相同,只是它的属性不是虚拟的,并且是不可变的,也就是说,属性只在构造函数中设置,进行更改,创建新对象),这是一种很好的做法将数据发送到外部意味着将DTO映射到ViewModel,而ViewModel只包含您想要显示的数据。我建议您阅读有关MVVM(Model View ViewModel)的内容,然后您应该理解为什么将所有这些内容分开很重要。好的,谢谢。我会认为你的答案是正确的。这是我的错误,BookModel不包含InventoryItemModel。但我建议你看看这篇关于延迟加载的帖子:。