[英]How to get foreign key linked values while using generic repository and unit of work patterns with Entity Framework Core
I am new to Entity Framework Core 7 and ASP.NET Core 7 MVC.我是 Entity Framework Core 7 和 ASP.NET Core 7 MVC 的新手。 I am learning the concepts using the Northwind database.我正在使用 Northwind 数据库学习这些概念。 I am using a generic repository and UnitOfWork pattern on top of EF Core for data access.我在 EF Core 之上使用通用存储库和 UnitOfWork 模式进行数据访问。
I have created a ProductsController
and in the view, I want to display all rows of the products in a grid view along with the corresponding category name and supplier name as the Products
table has Category ID
and Supplier ID
as foreign keys.我创建了一个ProductsController
并在视图中,我想在网格视图中显示产品的所有行以及相应的类别名称和供应商名称,因为Products
表具有Category ID
和Supplier ID
作为外键。
In the pure EF, I could have used .Include
to get these two values.在纯 EF 中,我可以使用.Include
来获取这两个值。 However, it's not available in the generic repository pattern.但是,它在通用存储库模式中不可用。 I'm sharing a relationship diagram of these three tables here:我在这里分享这三个表的关系图:
Code:代码:
// GET: ProductController
public ActionResult Index()
{
var products = _unitOfWork.Product.GetAll();
return View(products);
}
// Product model
public partial class Product
{
public int ProductId { get; set; }
[DisplayName("Product Name")]
public string ProductName { get; set; } = null!;
public int? SupplierId { get; set; }
public int? CategoryId { get; set; }
[DisplayName("Quantity Per Unit")]
public string? QuantityPerUnit { get; set; }
[DataType(DataType.Currency)]
public decimal? UnitPrice { get; set; }
public short? UnitsInStock { get; set; }
public short? UnitsOnOrder { get; set; }
public short? ReorderLevel { get; set; }
public bool Discontinued { get; set; }
public virtual Category? Category { get; set; }
public virtual ICollection<OrderDetail> OrderDetails { get;
} = new List<OrderDetail> ();
public virtual Supplier? Supplier { get; set; }
}
In the UnitOfWork
pattern, these three tables are available individually.在UnitOfWork
模式中,这三个表是单独可用的。 Essentially I want to know how to get the Category Name and Supplier Name from the Products
collection.本质上,我想知道如何从Products
集合中获取类别名称和供应商名称。
You can use the LINQ Join method to join the three tables and then project the result into a model object with properties for the Category Name and Supplier Name.您可以使用 LINQ Join 方法连接这三个表,然后将结果投影到 model object 中,其中包含 Category Name 和 Supplier Name 的属性。
var result = from p in _unitOfWork.Product.GetAll()
join c in _unitOfWork.Category.GetAll() on p.CategoryId equals c.CategoryId
join s in _unitOfWork.Supplier.GetAll() on p.SupplierId equals s.SupplierId
select new {
p.ProductId,
p.ProductName,
c.CategoryName,
s.CompanyName
};
return View(result);
In the view, you can access the CategoryName and SupplierName properties of the model object. Hope this helps.在视图中,您可以访问 model object 的 CategoryName 和 SupplierName 属性。希望这对您有所帮助。
In the UnitOfWork pattern, these three tables are available individually.在 UnitOfWork 模式中,这三个表是单独可用的。 Essentially I want to know how to get the Category Name and Supplier Name from the Products collection.本质上,我想知道如何从产品集合中获取类别名称和供应商名称。
Well, as you have Product
class and along with this class you have navigation class those are for instance as Categories
and Suppliers
, which has foreign table relationship with Product
class Navigation class好吧,因为你有Product
class 和这个 class 你有导航 class 那些例如Categories
和Suppliers
,它与Product
class导航 class有外部表关系
public class Categories
{
[Key]
public int CategoryID { get; set; }
public string? CategoryName { get; set; }
}
public class Suppliers
{
[Key]
public int SupplierID { get; set; }
public string? CompanyName { get; set; }
public string? ContactName { get; set; }
}
How To Load Related Entities From Navigation Table In Unit Of Work Pattern:如何从工作单元模式中的导航表加载相关实体:
In your scenario, we can extent our GenericRepository
To Product Repository then we can use .Include
object which help to query data from related table property which would be more convenient and efficient.在您的场景中,我们可以将我们的GenericRepository
扩展到 Product Repository 然后我们可以使用.Include
object 这有助于从相关表属性中查询数据,这将更加方便和高效。 In your scenario, When we will query upon Product
table at the same time we would like to fetch data related to other table as well right, so have a look below:在您的场景中,当我们同时查询Product
表时,我们也想获取与其他表相关的数据,所以请看下面:
UnitOfWork Repository For Product:产品的 UnitOfWork 存储库:
public class ProductRepository : GenericRepository<Product>, IProductReposiotry
{
public ProductRepository(ApplicationDbContext context, ILogger logger) : base(context, logger) { }
public override async Task<IEnumerable<Product>> All()
{
try
{
var products = context.Products.Include(cat => cat.Category).Include(sup=>sup.Supplier).ToList();
return await dbSet.ToListAsync();
}
catch (Exception ex)
{
_logger.LogError(ex, "{Repo} All function error", typeof(ProductRepository));
return new List<Product>();
}
}
}
UnitOfWork DbContext:工作单元 DbContext:
public class ApplicationDbContext : DbContext
{
public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
: base(options)
{
}
public DbSet<Product> Products { get; set; }
public DbSet<Categories> Categories { get; set; }
public DbSet<Suppliers> Suppliers { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Product>().ToTable("Products");
modelBuilder.Entity<Categories>().ToTable("Categories");
modelBuilder.Entity<Suppliers>().ToTable("Suppliers");
}
}
Note: Please be sure about the Northwind
database,property and your class follow same case.注意:请确保Northwind
数据库、属性和您的 class 遵循相同的大小写。
UnitOfWork Controller:工作单元 Controller:
public class UnitOfWorkProductController : Controller
{
private readonly ILogger<UnitOfWorkProductViewController> _logger;
private readonly IUnitOfWork _unitOfWork;
public UnitOfWorkProductViewController(
ILogger<UnitOfWorkProductViewController> logger,
IUnitOfWork unitOfWork)
{
_logger = logger;
_unitOfWork = unitOfWork;
}
public async Task<IActionResult> Index()
{
var products = await _unitOfWork.Products.All();
return View(products);
}
}
View:看法:
@model IEnumerable<YourProjectName.Models.Product>
<table class="table">
<thead>
<tr>
<th>ProductId
<th>ProductName
<th>Supplier Name
<th>Category Name
<th>UnitPrice
</tr>
</thead>
<tbody>
@foreach (var item in Model)
{
<tr>
<td>@item.ProductId</td>
<td>@item.ProductName</td>
<td>@item.Supplier?.CompanyName</td>
<td>@item.Category?.CategoryName</td>
<td>@item.UnitPrice</td>
</tr>
}
</tbody>
</table>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.