【问题标题】:EF: Select all that are not in another tableEF:选择所有不在另一个表中的
【发布时间】:2021-01-26 11:13:47
【问题描述】:

我是实体框架的新手。就我而言,我有两个表:Device 存储所有设备,AssignedDevice 存储在某个时间分配的所有设备。

我写了一个选择,选择了所有Devices,目前没有分配。

您可以在下面找到表格、选择和我的问题:

Device的模型类:

public class Device 
{
        [Key]
        public string SerialNumber { get; set; }

        [Required]
        public string Type { get; set; }

        public virtual Brand Brand { get; set; }

        [ForeignKey("Brand")]
        [Required]
        public int BrandId { get; set; }

        [Required]
        public string Model { get; set; }

        public Device()
        {
        }
}

AssignedDevice的模型类:

public class AssignedDevice
{
        [Key]
        public int Id { get; set; }
        
        [Required]
        public Device Device { get; set; }

        [ForeignKey("Device")]
        public string DeviceId { get; set; }

        [Required]
        public int StudentId { get; set; }

        [Required]
        public DateTime AssignedFrom { get; set; }

        [Required]
        public DateTime AssignedUntil { get; set; }

        public IdentityUser Assignee { get; set; }
        
        [ForeignKey("Assignee")]
        [Required]
        public string AssigneeId { get; set; }

        public AssignedDevice()
        {
        }
}

这是我的“选择”:

var query = _dbContext.Devices.Join(
                _dbContext.AssignedDevices,
                device => device.SerialNumber,
                assignedDevice => assignedDevice.Device.SerialNumber,
                (device, assignedDevice) => new 
                {
                    serialNumber = device.SerialNumber,
                    type = device.Type,
                    brand = device.Brand.BrandName, 
                    model = device.Model,
                    assignedFrom = assignedDevice.AssignedFrom,
                    assignedUntil = assignedDevice.AssignedUntil
                })
                .Where(assignedDevice => assignedDevice.assignedFrom > System.DateTime.Now || assignedDevice.assignedUntil < System.DateTime.Now)
                .ToList();

我的问题是:

如何选择所有在Device 中但不在AssignedDevice 中的项目?

数据必须在同一个select中选择,我已经写好了。

感谢您的回答。

【问题讨论】:

  • 你可以使用Except方法,类似stackoverflow.com/a/42515973/2946329
  • 一般方法(来自 SQL 世界)是使用left outer join(可以在 LINQ 中模拟)结合right == null 条件。但是,您不能使用相同的选择,因为assignedDevice 将是null,因此您需要进行一些修改,例如使结果assignedFromassignedUnitil 属性可为空。 EF(核心)方式虽然是定义集合导航属性并使用它而不是连接。例如如果没有投影,您所要求的条件将类似于_dbContext.Devices.Where(device =&gt; !device.AssignedDevices.Any())
  • 你看这个问题了吗stackoverflow.com/questions/21766856/…_dbContext.Devices.Where(ad =&gt; !_dbContext.AssignedDevices.Select(d =&gt; d.DeviceId).Contains(ad.DeviceId));

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


【解决方案1】:

要解决您的问题,您需要使用左连接而不是内连接。这是在 LINQ 查询中模拟左连接的简单方法,使用 .DefaultIfEmpty()

var query = 
    from d in _dbContext.Devices
    from ad in _dbContext.AssignedDevices.Where(ad => ad.DeviceId == d.Id).DefaultIfEmpty()
    where ...
    select ...

如果您希望查询结果中的“正确”表中的字段,则必须处理空引用:

select new 
{
    AssignedFrom = ad != null ? ad.AssignedFrom : (DateTime?)null,
    ...
}

基本上就是 Ivan Stoev 在他的评论中所说的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-13
    • 1970-01-01
    • 2022-11-13
    • 2021-12-30
    • 2011-03-30
    • 2016-02-29
    相关资源
    最近更新 更多