c# - 如何编写 EF Core 查询以过滤多个表?

标签 c# asp.net-core entity-framework-core

将 ASP Core 2 与 EF Core 和 SQL Server 结合使用。我有一个我认为是检索给定分销商的制造商(或个别制造商)列表的简单任务。

Users 表提供经过身份验证的用户,每个用户都与一个分销商相关联(在模型中表示为 _user )。所以,当 Action GetManufacturers()ManufacturersController 上调用,它应该返回给定经销商的所有制造商。同样GetManufacturers(int id)应该返回一个制造商,前提是它与经过认证的分销商相关联。

Tables

为此,我正在尝试各种公式,例如:

await _context.Manufacturers
    .Include(a => a.Addresses)
    .Include(m => m.DistributorManufacturers)
    .Where (a => a.AddressesNavigation.State = "CA")
    .Where (m => m.Id == id)   // Manufacturers Id
    .Where (d => d.DistributorManufacturers.DistributorId == _user.DistributorId)
    .AsNoTracking()
    .ToListAsyc()

VS 提示 ICollection<DistributorManufacturers>不包含 DistributorId 的定义(即使我从类里面复制/粘贴了它)。它在概念上与我的地址过滤器没有区别。

我也试过 .ThenInclude添加 Distributors 表,但没有成功。

DistributorManufacturers 表是使用 Scaffold-DbContext 创建的,并定义了外键和导航属性。

最佳答案

因此,做了一些工作来重新创建您的模型。我唯一改变的是我在 Distributor 表中添加了 userId 而不是相反。这将是一个很长的答案..所以等一下

模型(省略了 User 和 Address 实体,因为它们没有什么特别之处)

public abstract class Entity
{
    public int Id { get; set; }
}

public class Distributor : Entity
{   
    public User User { get; set; }

    public int UserId { get; set; }

    public Address Address { get; set; }

    public int AddressId { get; set; }

    public ICollection<DistributorManufacturer> DistributorManufacturers { get; set; }
}

public class Manufacturer : Entity
{
    public Address Address { get; set; }

    public int AddressId { get; set; }

    public ICollection<DistributorManufacturer> DistributorManufacturers { get; set; }
}

public class DistributorManufacturer
{
    public Distributor Distributor { get; set; }

    public int DistributorId { get; set; }

    public Manufacturer Manufacturer { get; set; }

    public int ManufacturerId { get; set; }
}

配置如下:

modelBuilder.Entity<Distributor>()
    .HasOne(p => p.User)
    .WithMany()
    .HasForeignKey(p => p.UserId);

modelBuilder.Entity<Distributor>()
    .HasOne(p => p.Address)
    .WithMany()
    .HasForeignKey(p => p.AddressId);

modelBuilder.Entity<Manufacturer>()
    .HasOne(p => p.Address)
    .WithMany()
    .HasForeignKey(p => p.AddressId);

// many to many mapping
modelBuilder.Entity<DistributorManufacturer>()
    .HasKey(bc => new { bc.DistributorId, bc.ManufacturerId });

modelBuilder.Entity<DistributorManufacturer>()
    .HasOne(bc => bc.Distributor)
    .WithMany(b => b.DistributorManufacturers)
    .HasForeignKey(bc => bc.DistributorId)
    .OnDelete(DeleteBehavior.Restrict);

modelBuilder.Entity<DistributorManufacturer>()
    .HasOne(bc => bc.Manufacturer)
    .WithMany(c => c.DistributorManufacturers)
    .HasForeignKey(bc => bc.ManufacturerId)
    .OnDelete(DeleteBehavior.Restrict);

插入这个值:

select * from Users
select * from Distributors
select * from Manufacturers
select * from DistributorManufacturers

enter image description here

然后,在 GetManufacturers() 操作中,您想要为登录的 Distributor 返回所有 Manufacturers,也就是 User。 (这是我对你的问题的假设。如果我错了,请纠正我)。所以,向下查询:

// Simulate getting the Id of the logged in User.
var userId = 1;

var query = (from m in _context.Manufacturers
             join dm in _context.DistributorManufacturers on m.Id equals dm.ManufacturerId
             join dist in _context.Distributors on dm.DistributorId equals dist.Id
             join adrs in _context.Addresses on m.AddressId equals adrs.Id
             where dist.UserId == userId
             select new
             {
                 ManufacturerId = m.Id,
                 ManufacturerName = m.Name,
                 DistributorId = dist.Id,
                 DistributorName = dist.Name,
                 Address = adrs
             }).ToList();

结果是:

[
    {
        "manufacturerId": 1,
        "manufacturerName": "Manufacturer 1",
        "distributorId": 1,
        "distributorName": "Distributor 1",
        "address": {
            "street": "Street 1",
            "city": "New York",
            "state": "NY",
            "id": 1
        }
    },
    {
        "manufacturerId": 2,
        "manufacturerName": "Manufacturer 2",
        "distributorId": 1,
        "distributorName": "Distributor 1",
        "address": {
            "street": "Street 2",
            "city": "New York",
            "state": "NY",
            "id": 2
        }
    }
]

要使 GetManufacturers(int id) 正常工作,只需将 Manufacturer Id 添加到 where 子句中。由于它在 DistributorManufacturer 上执行内部联接,如果与登录用户没有任何关系,它将返回 null。

注意:在 EF Core 中,当您拥有多对多关系时,您需要(至少现在……)将联合表作为一个实体。您可以在此处查看有关此的讨论:https://github.com/aspnet/EntityFrameworkCore/issues/1368

关于c# - 如何编写 EF Core 查询以过滤多个表?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48968105/

相关文章:

c# - context.EnsureCreated() 抛出异常 - 已经有一个名为的表

c# - 代码组织 : How to best group functions, 类等

c# - 如何以编程方式或使用命令行程序更新现有 CA 模板的有效期

c# - aspnet 核心集成测试返回 404

Elasticsearch NEST 重用 ElasticClient 进行不同的索引查询

c# - EF Core 包含列表列表

c# - EF Core 6.0 无效操作异常 : The object has been removed from the model

c# - 使派生类无法访问但仍然公开的方法

c# - LINQ to SQL是否支持t-sql "in"语句

linux - .net核心应用程序在linux上作为守护程序运行的问题