【问题标题】:Querying an auto-generated EF junction table查询自动生成的 EF 联结表
【发布时间】:2012-11-06 10:16:18
【问题描述】:

我有两个模型,Benefit 和 SchemeName

好处-

[Key]
public int BenefitID { get; set; }
public string BenefitName { get; set; }
public string BenefitDescription { get; set; }
public virtual ICollection<SchemeName> SchemeNames { get; set; }

方案名称

[Key]
public int SchemeNameID { get; set; }
public string Name { get; set; }
public virtual ICollection<Benefit> Benefits { get; set; }

这已在数据库 Benefits、SchemeNames 和一个名为 SchemeNameBenefits 的连接表中创建了三个表。

我正在尝试填充一个下拉列表,其中仅包含与某个 Benefit 关联的 SchemeNames,但我不确定如何执行此操作,我可以在我的代码中引用连接表吗?

我从以下开始(返回所有 SchemeNames)

private void PopulatePensionSchemeName(object selectedPensionSchemeName = null)
        {
            var schemeNameQuery = from d in db.SchemeNames
                                  orderby d.SchemeNameID
                                  select d;

            ViewBag.PensionSchemeNameID = new SelectList(schemeNameQuery, "SchemeNameID", "Name", selectedPensionSchemeName);
        }

但我不确定如何添加此子句。有什么指点吗?

【问题讨论】:

    标签: c# asp.net-mvc linq entity-framework ef-code-first


    【解决方案1】:

    您需要使用 SchemeNames 的 Benefit 对象的键。您可能正在寻找的查询是:-

    var benefitId = // However you get your benefit Id
    
    var schemaNameQuery = from b in db.Benefits
                          from s in b.SchemeNames
                          where b.BenefitId == benefitId
                          select s;
    

    或者在扩展方法语法中:-

    var schemaNameQuery = db.Benefits.Where(b.BenefitId == benefitId)
                                     .SelectMany(b => b.SchemeNames);
    

    这会产生以下 SQL:-

    SELECT ...
    FROM [dbo].[SchemeNameBenefits] AS [Extent1]
    INNER JOIN [dbo].[SchemeNames] AS [Extent2]
      ON [Extent1].[SchemeName_Id] = [Extent2].[SchemeNameId]
    WHERE [Extent1].[Benefit_Id] = @p__linq__0
    

    您也可以使用:-

    var benefitId = // However you get your benefit Id
    
    var schemeNameQuery = from d in db.SchemeNames
                          where d.Benefits.Any(x => x.Id == benefitId)
                          orderby d.SchemeNameId
                          select d;
    

    这会产生以下 SQL:-

    SELECT ...
    FROM ( SELECT ... FROM [dbo].[SchemeNames] AS [Extent1]
           WHERE EXISTS (SELECT 1 AS [C1]
                         FROM [dbo].[SchemeNameBenefits] AS [Extent2]
                         WHERE ([Extent1].[SchemeNameId] = [Extent2].[SchemeName_Id])
                         AND ([Extent2].[Benefit_Id] = @p__linq__0)))
    AS ...
    ORDER BY [Project2].[Id] ASC
    

    请注意,在这两种情况下,生成的 SQL 都会引用您的联结表即使它不是您的 EF 模型的一部分。

    如果您已经拥有 Benefit 对象,当然,您可以更简单地使用以下方法获取其 SchemeNames:-

    var schemeNameQuery = benefit.SchemeNames;
    

    【讨论】:

      【解决方案2】:

      我会通过使用连接表来做到这一点。连接表是您的连接表。它将由两个外键组成,SchemeNameID 和 BenefitID。

      查看此网站以了解有关 Junction Tables 的更多信息:

      http://megocode3.wordpress.com/2008/01/04/understanding-a-sql-junction-table/

      这对我帮助很大。

      【讨论】:

        【解决方案3】:

        [免责声明] 以现有或添加 SchemeNameBenefits 模型为条件,以下应该可以工作。

        所以看起来 SchemeNameBenefits 表是一个多对多映射,在这种情况下使用福利 ID 来获取方案 ID 的集合

        var schemeIds = db.SchemeNamesBenefits.Where(map => map.BenefitID == id)
                                              .Select(map => map.SchemeNameID).ToArray();
        

        然后拉回这些方案ID的所有方案名称信息

        var result = db.SchemeNames.Where(scheme => schemeIds.Contains(scheme.SchemeNameID))
                                   .OrderBy(scheme => scheme.SchemeNameId)
                                   .Select(scheme => scheme.Name).ToArray();
        

        或者在一个查询中

         var result = db.SchemeNamesBenefits.Where(map => map.BenefitID == id)
                                            .SelectMany(map => db.SchemeNames
                                                                 .Where(scheme => map.SchemeNameID == scheme.SchemeNameID)
                                                                 .OrderBy(scheme => scheme.SchemeNameId)
                                                                 .Select(scheme => scheme.Name)
                                                                 .AsEnumerable())
                                            .ToArray()
        

        【讨论】:

        • 谢谢,但我的问题实际上是如何在我的代码中使用 SchemeNamesBenefits 表。我从未为此创建模型,它只是在我创建其他两个模型时作为表添加到数据库中。
        • 嗨 Martin,正如 Derek 所提到的,SchemeNamesBenefits 表是计划和福利之间的映射,因此在这种情况下,一个计划可以有很多好处,一个福利可以是许多计划的一部分。您将必须自己填充此表,然后您就可以像我上面的回答那样对其进行查询。或者,根据 Iain 的回答,如果您查询 SchemeName 对象的好处属性,提供者将隐式使用它。
        • 我确信 Martin 了解什么是联结表。他的问题是 SchemeNameBenefits 不是他的模型的一部分。 IE。没有 db.SchemeNameBenefits 属性。
        • 很公平,然后把棒子弄错了,将进行适当的编辑。
        猜你喜欢
        • 1970-01-01
        • 2021-10-22
        • 2017-12-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-12-03
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多