简体   繁体   English

如何在 Entity Framework Core 中使用通用存储库和工作单元模式时获取外键链接值

[英]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 IDSupplier 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 那些例如CategoriesSuppliers ,它与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>

Output: Output: 在此处输入图像描述

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用实体框架使用存储库和单元工作模式正确处置? - Correct disposing using Repository and Unit Work patterns with Entity Framework? 实体框架通用存储库-外键异常更新实体关系 - Entity framework generic repository - Foreign key exception updating entity relationship 如何使用Entity Framework + Repository + Working of Work启动应用程序? - How to start an application using Entity Framework + Repository + Unit of Work? 存储库和工作单元:实体没有基于外键值加载 - Repository And Unit Of Work : Entity no loading based on foreign key value 具有通用存储库和工作单元存储的实体框架显示旧数据 - Entity framework with generic repository and Unit of Work store showing old data "如何在 Entity Framework Core 中定义外键" - How to define foreign Key in Entity Framework Core 实施通用存储库和工作单元模式 - Implementing the generic repository and unit of work patterns Net Core:通用存储库主 ID 实体框架中的关键性能 - Net Core: Generic Repository Primary Id Key Performance in Entity Framework 使用Moq进行单元测试的工作单元和通用存储库模式框架 - Unit Testing Unit of Work and Generic Repository Pattern framework using Moq 使用单元测试、工作单元和通用存储库模式框架从 MOQ 中获取单个对象 - Get single object from MOQ using Unit Testing, Unit of Work and Generic Repository Pattern framework
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM