【问题标题】:Calling a function within Entity Framework Select在实体框架选择中调用函数
【发布时间】:2015-02-25 16:09:06
【问题描述】:

我的对象(oJobs)的一个属性如下:

    Private _brandlist As List(Of DAL.Brand)
    Public Property PostBrandList() As List(Of DAL.Brand)
        Get
            Return _brandlist
        End Get
        Set(ByVal value As List(Of DAL.Brand))
            _brandlist = value
        End Set
    End Property

在数据库中,品牌列表存储为以逗号分隔的字符串,例如'brands' 列可以是字符串 '3,45,2',其中每个数字代表存储在另一个表中的品牌 ID。

我的选择查询如下:

Dim jobposts As List(Of oJobs) = From j In db.JobPostings
Select New oJobs With {                                                                  'hiding all others for code brevity
    .PostBrandList = 'problem is here'
}

由于j.BrandList 将返回一个字符串,我需要拆分该字符串并为每个数字运行另一个查询以最终返回并将 List(Of DAL.Brand) 分配给.PostBrandList

对于那些可能会问“你尝试过什么?”的人,

  • 我已经运行了查询,然后为每个添加了品牌列表 - 成功但不是最佳的
  • 编写了一个将列表作为参数并返回一个单独的对象列表的函数 - 非常愚蠢。

另外,我不允许规范化数据库:(

【问题讨论】:

  • 发送查询以检索您已经尝试过的 ID 列表。创建一个带有 ID 的数组并发送第二个查询并使用 .Contains 获取所有带有 ID 的实体。或者,在数据库中创建一个执行此操作的存储过程。
  • 正确的做法是删除您的品牌栏。这就是我们所说的内部平台效应,它不是在 RDBMS 中处理关系数据的正确方法。您应该有一个表格,将您的品牌与您的工作联系起来。由于更好的索引等,从长远来看,这将有所帮助。
  • 嗨 Aron,请阅读我的最后一句话。否则我完全同意你的看法,并尝试了很多改变一些想法!
  • 您刚才在代码中提到“问题就在这里”——但问题是什么?你得到了哪些错误?请将错误消息添加到您的问题中。您提到了字符串操作 - 这些在 EF 中可能会出现问题:您正在使用哪些字符串操作?

标签: vb.net entity-framework linq-to-entities entity-framework-6


【解决方案1】:

未经测试,可能需要一些调整,但这里有一个想法。您还需要将您的属性更改为 IEnumerable 而不是 List。因为第二个 linq 查询嵌入在第一个查询中,我相信它应该作为一个查询执行,但您应该检查它以确保。

Dim jobposts As List(Of oJobs) = From j In db.JobPostings
Select New oJobs With {                                                                  'hiding all others for code brevity
    .PostBrandList = From b In db.Brands Where j.Brands = b.ID Or j.Brands.StartsWith(b.ID & ",") Or j.Brands.EndsWith("," & b.ID) Or j.Brands.Contains("," & b.ID & ",") Select b
}

【讨论】:

    【解决方案2】:

    在c#中你可以使用

    .Select(x=>new {x.BrandList})
    .ToList() //Materialize first before calling function
    .Select(x=> new oJobs{
        PostBrandList = 
            db.Brands.Where(z=>
            x.BrandList
                .Split(',')
                .Select(y=>int.Parse(y.Trim()))
                .Contains(z.Id))
                .ToList()
    });
    

    注意在调用String.Split之前必须先实现实体 我不知道如何将其转换为 VB.NET。 当然会导致SELECT n+1的问题,因为你不能使用join。

    如果你不能规范化表,我的另一个建议是创建索引视图(sql server),这样你就可以使用连接并提高性能。

    索引视图https://msdn.microsoft.com/en-us/library/ms191432.aspx

    【讨论】:

      【解决方案3】:

      您可以尝试使用Let 语句:

      Dim jobposts As List(Of oJobs) = From j In db.JobPostings
      /* li in the LINQ Statement represents one string value from the BrandList list */
      Let postBrandElemsList = j.BrandList.Split(',').Select(Function(li) New DAL.Brand With { ... /* Field initializatione of the Class DAL.Brand here */ }
      Select New oJobs With 
      {
          .PostBrandList = postBrandElemsList
      }
      

      对于可能不好的 VB.NET 语法,我很抱歉,您应该在代码中实现它时检查这一点。

      【讨论】:

        【解决方案4】:

        也许您只想将列 Brands 上的 Split 函数使用到一个数组中并遍历结果,使用 Find 函数检索品牌对象?

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-12-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-10-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多