如何使用 EF Core 将文本 {12,13} 转换为 int 列表

问题描述 投票:0回答:1

我正在开发一个应用程序,我将记录保存在文本列中,例如

{ 12, 13, 14 }
。当我尝试将数据绑定到字符串属性时,我得到以下结果:

System.Linq.Enumerable+SelectArrayIterator`2[System.String,System.Int32]

下面是我的查询,我需要获取整数列表中的 ID。但正如我们在

IQueryable
中所知,我们无法定义任何拆分或任何方法。

public async Task<BaseResponseModel> GetAnswer(int id = 0)
{
    response.SuccessModel();

    try
    {
        var answers = await _context.OfferAnswers
                .Where(s => (id != 0 ? s.id == id : true) && s.is_deleted == false && s.is_active == true)
                .Join(
                    _context.OfferQuestions.Where(q => q.is_active == true && q.is_deleted == false),
                    a => a.question_id,
                    q => q.id,
                    (a, q) => new { answer = a, question = q }
                )
                .Join(
                    _context.Packages.Where(p => p.is_active == true && p.is_deleted == false),
                    q => q.question.package_id,
                    p => p.id,
                    (q, p) => new { answer = q.answer, question = q.question, package = p }
                )
                .Select(s => new
                {
                    PackageId = s.question.package_id,
                    Package = s.package.package_name,
                    QuestionId = s.answer.question_id,
                    Question = s.question.question,
                    AnswerId = s.answer.id,
                    AddOnIds = s.answer.addon_ids,
                    Answer = s.answer.answer,
                    Description = s.answer.description,
                    url = s.answer.icon,
                    AnswerType = s.answer.answer_type_id,
                    Product = s.answer.product_ids == null ? null :
                        _context.Products
                            .Join(
                                _context.PackageDetails
                                    .Where(pd => pd.is_active == true && pd.is_deleted == false && pd.package_id == s.question.package_id),
                                p => p.id,
                                pd => pd.product_id,
                                (p, pd) => new { product = p, productdetail = pd }
                            )
                            .Select(p => new
                            {
                                ProductId = p.product.id,
                                ProductName = p.product.product_name
                            })
                            .ToList(),
                    Addon = s.answer.addon_ids == null ? null :
                        _context.add_Ons
                            .Join(
                                _context.PackageDetails
                                    .Where(ad => ad.is_active == true && ad.is_deleted == false && ad.package_id == s.question.package_id),
                                a => a.id,
                                ad => ad.add_on_id,
                                (a, ad) => new { addon = a, addondetail = ad }
                            )
                            .Select(a => new AddonDto
                            {
                                AddonId = a.addon.id,
                                AddonName = a.addon.add_on_name,
                                ListIds = s.answer.addon_ids
                            })
                            .ToList()
                })
                .ToListAsync();
        response.Data = id != 0 ? answers.FirstOrDefault() : answers.ToList();
        response.ResponseMessage = "Packages fetched successfully.";
    }
    catch (Exception ex)
    {
    }

    return response;
}

AddOnDto
班级:

public class AddonDto
{
       public AddonDto()
       {
           this.AddonIds = new List<int>();
       }

       public int AddonId { get; set; }
       public string? AddonName { get; set; }
       public List<int> AddonIds { get; set; }
       private string _listIds; // backing field for ListIds
       public string ListIds {get; set;}
}

这是表格的屏幕截图:

c# entity-framework linq asp.net-core
1个回答
0
投票
理想情况下,您应该考虑使用具有一对多或多对多关系的正确规范化模式,因为它可以比使用字符串更有效地正确索引和搜索。如果您确实需要将分隔列表之类的内容存储为字符串,您可以使用未映射的属性将字符串转换为所需的结构:

公共类AddonDto { 公共 int AddonId { 获取;放; } 公共字符串?插件名称 { 获取;放; } 私有字符串_listIds; 公共字符串 ListId { 获取=>_listIds; 放 { _listIds = 值; _addonIds = null; }

}

private List<int>? _addonIds = null; [NotMapped] // If this is an entity class so EF doesn't try and map this property. public IReadOnlyCollection<int> AddonIds { get { return _addonIds ??= new List<int>(ListIds .Split(',', StringSplitOptions.RemoveEmptyEntries) .Select(x => int.Parse(x)); } }
}

如果您想更改关联的附加组件,请公开“AddAddon(int)”和“RemoveAddon(int)”等操作方法,它们可以向支持集合添加或删除所需的 Id 并更新 ListIds 字符串。请注意,如果 ListIds 字符串允许设置器,则应删除后备集合以确保重新计算它以反映当前字符串。

当涉及实体内的分隔字符串时,我建议使用有边缘的分隔符,其中每个条目的两侧总是可以找到分隔符。例如,使用管道分隔符而不是“1,2,3,4”,您将得到“|1|2|3|4|”上述基于拆分的逻辑适用于任一分隔符模式/字符,但在 Linq 中高效查询数据时,您不能在 Linq 查询中使用“AddonIds”(

List<int>

),您需要对字符串支持执行 
Contains
场地。使用边缘分隔符,您可以执行类似 
.Where(x => x.ListIds.Contains($"|{addonId}|"))
 的操作来查找包含分隔的 addonId 值的条目。使用逗号分隔的列表,如果您执行 
.Where(x => x.ListIds.Contains(addonId))
 搜索 Id #1 将找到“1”、“10”、“11”、“21”,并且不能依赖 
.Where(x => x.ListIds.Contains($",{addonId},"))
,因为这不会找到条目其中“1”是第一个或最后一个条目。使用边缘分隔符,它将专门查找包含“|1|”的条目“1”是否在正面、背面或中间,并且仅匹配找到“1”的情况,而不匹配“|10|”的情况例如。

© www.soinside.com 2019 - 2024. All rights reserved.