简体   繁体   English

EF Core 枚举集合属性比较

[英]EF Core enum collection property comparing

I'm using code first with Entity Framework Core for handling som addresses in an application.我在 Entity Framework Core 中使用代码优先来处理应用程序中的 som 地址。 These addresses all have a HousingTypes property which is a collection of enums that can by any of the available enum types.这些地址都有一个 HousingTypes 属性,它是一个枚举集合,可以由任何可用的枚举类型组成。

public enum HousingType
{
    Condominium = 1,
    SummerHouse = 2,
    StudentApartment = 3,
    ServiceHousing = 4
}

public class Address
{
    public int Id { get; set; }
    public ICollection<HousingType> HousingTypes { get; set; }
}

I've created a ValueConverter and ValueComparer as described by others previously to convert these value to comma separated strings in the database like this in the DatabaseContext:我已经按照其他人之前的描述创建了一个 ValueConverter 和 ValueComparer,以便将这些值转换为数据库中以逗号分隔的字符串,就像在 DatabaseContext 中这样:

ModelBuilder.Entity<Address>().Property(nameof(HousingTypes))
    .HasConversion(
        x => string.Join(",", x),
        x => string.IsNullOrWhiteSpace(x) ? new List<HousingType>() : x.Split(new[] { ',' }).ToList()))
    .Metadata.SetValueComparer(new ValueComparer<ICollection<HousingType>>(
        (x, y) => x.SequenceEqual(y),
        x => x.Aggregate(0, (a, v) => HashCode.Combine(a, v.GetHashCode())),
        x => x.ToList()););

This is all and well, and I can read and write data as normal.一切都很好,我可以正常读写数据。 But I've come to a point where the user needs to filter out addresses depending on selected HousingTypes.但我已经到了用户需要根据所选 HousingTypes 过滤掉地址的地步。 Now Entity Framework does not know how to compare multiple housing types to each other.现在 Entity Framework 不知道如何将多种住房类型相互比较。

// Only receive addresses that has any of these housing types included
var filterExample = new HousingType[] { HousingType.Condominium, HousingType.SummerHouse };

await _context.Addresses
    .Where(a => a.HousingTypes.Any(ht => filterExample.Contains(ht))) // Entity Framework does not like this!
    .ToListAsync;

When retrieving the data I get the following error message:检索数据时,我收到以下错误消息:

The LINQ expression 'ht => __filterExample_3.Contains(ht)' could not be translated.无法翻译 LINQ 表达式“ht => __filterExample_3.Contains(ht)”。 Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'.以可翻译的形式重写查询,或通过插入对“AsEnumerable”、“AsAsyncEnumerable”、“ToList”或“ToListAsync”的调用显式切换到客户端评估。

I would rather not inserting a call to ToList earlier, since that would load in all addresses (lots amounts of data) that is not needed, and makes it problematic to use paging and such when retrieving data.我宁愿不提前插入对 ToList 的调用,因为那样会加载不需要的所有地址(大量数据),并且在检索数据时使用分页等会产生问题。

First I tried using Flags with the enum, but this complicated a lot of the code (specially to make it compatible with the front-end).首先,我尝试将 Flags 与枚举一起使用,但这使很多代码变得复杂(特别是为了使其与前端兼容)。

Also, it's not intuitive how to make comparisons between two enums and compare wether they are included in each other or not, etc. This could of course be made simpler with help or extension methods.此外,如何在两个枚举之间进行比较以及比较它们是否包含在彼此中等并不直观。这当然可以通过帮助或扩展方法变得更简单。

But I ended up using foreign key tables for this instead.但是我最终为此使用了外键表。 Adding a AddressHousingType model which contains a normal enum and a foreign key to Address (one to many relation).添加一个 AddressHousingType model,它包含一个普通枚举和一个外键到地址(一对多关系)。

This solution is not ideal either, but works and is simpler to understand.这个解决方案也不理想,但有效并且更容易理解。 I think that if this was a new project I would consider comparing bitwise and creating help methods for this, but since this is a project that has been in development for quite some time this felt like the best solution this time.我认为,如果这是一个新项目,我会考虑按位比较并为此创建帮助方法,但由于这是一个已经开发了很长时间的项目,所以这次感觉是最好的解决方案。

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM