如何选择外键上的记录

时间:2018-10-17 06:22:28

标签: sql entity-framework linq linq-to-sql linq-to-entities

我正在尝试从表中选择与单个记录匹配相同外键的记录记录。我编写了以下有效的SQL,但我想知道是否有更优化的方法:

SELECT title FROM table1 r INNER JOIN dbo.table2 a ON a.Id = r.AssetStructureId 
                              INNER JOIN table3 s ON s.Id = a.table3id 
                              INNER JOIN dbo.table4 f ON f.Id = s.table4id
WHERE s.table4id = (SELECT f.Id FROM dbo.table4 f 
                                     INNER JOIN table3 s ON s.table4id = f.Id 
                                     INNER JOIN dbo.table2 a ON a.table3id = s.Id 
                                     INNER JOIN dbo.table1 r ON r.table2id = a.Id WHERE r.id = 21803)

我在实体框架中也写了相同的东西,但是写了两行,但是我想知道那里是否还有更好,更优化的方法?

var data = _context.table1.Where(x => x.Id == id).Select(x => new { x.table2.table3.table4id }).SingleOrDefault();
var titles = _context.table1.Where(x => x.table2.table3.table4Id == data.table4id).Select(x => new { x.Title });

任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:0)

您真可惜忘记给我们提供您的课程和规格!

尝试理解您的SQL之后,看来table1有一个AssetStructureId,这是Table2所属的Table1的外键。可能是一对多关系。

Table2具有Table3Id所属Table3的外键Table2,也是一对多关系

最后,Table3Table4Id所属的Table4具有外键Table3

我,您确实喜欢标识符的专有名称,对吗?

所以:

  • 每个Table4Element的零个或多个Table3Elements
  • 每个Table3Element的零个或多个Table2Elements
  • 每个Table2Element具有零个或多个Table1Elements

entity framework code-first conventions之后,您将拥有类似于以下内容的课程:

class Table4Element
{
     public int Id {get; set;}

     // every Table4Element has zero or more Table3Elements:
     public virtual ICollection<Table3Element> Table3Elements {get; set;}

     ... // other properties
}
class Table3Element
{
     public int Id {get; set;}

     // every Table3Element has zero or more Table2Elements:
     public virtual ICollection<Table2Element> Table2Elements {get; set;}

     // every Table3Element belongs to exactly one Table4Element using foreign key
     public int Table4ElementId {get; set;}
     public virtual Table4Element Table4Element {get; set;}

     ...
}
  

在实体框架中,表的列由   非虚拟性质;虚拟属性代表关系   在表之间。

Table2Table1相似:

class Table2Element
{
     public int Id {get; set;}

     // every Table2Element has zero or more Table1Elements:
     public virtual ICollection<Table1Element> Table1Elements {get; set;}

     // every Table2Element belongs to exactly one Table3Element using foreign key
     public int Table3ElementId {get; set;}
     public virtual Table3Element Table3Element {get; set;}

     ...
}

class Table1Element
{
     public int Id {get; set;}

     // every Table1Element belongs to exactly one Table2Element using foreign key
     public int Table2ElementId {get; set;}
     public virtual Table2Element Table2Element {get; set;}

     ...
}

最后是您的DbContext

class MyDbContext : DbContext
{
    public DbSet<Table1Element> Table1Elements {get; set;}
    public DbSet<Table2Element> Table2Elements {get; set;}
    public DbSet<Table3Element> Table3Elements {get; set;}
    public DbSet<Table4Element> Table4Elements {get; set;}
}

这是实体框架确定表和列的名称以及表之间的关系所需要的全部。如果由于某种原因您想要不同的表名或列,则需要添加属性或使用流畅的API。

最重要的是,您已正确设置了虚拟属性。
无论何时使用虚拟属性,实体框架都知道需要一个(组)联接,并且会为你做的

现在我们已经定义了四个表,可以开始了

返回您的问题

糟糕,您忘记指定要选择的内容!

很显然,您的四个表之一都有一个Title。尽管您没有这么说,但我认为TitleTable1的属性。似乎您要从Id的{​​{1}}中选择拥有此Table1Element的{​​{1}}的{​​{1}}

输入:Title = 21803

  • 带有ID A的Table4Element具有一个Table4
  • 具有外键Table4ElementId A的Table3Element具有ID B
  • 具有外键Table3ElementId B的Table2Element具有ID C
  • 具有外键Table3ElementId C的Table1Element具有ID 21803

您想要Table1Element

使用虚拟属性使查询变得简单。实体框架将为您执行联接:

RequestedId

非常直观且易于理解。

我不知道为什么,但是有些人坚持自己做连接。使用方法语法将四个表连接起来看起来很可怕:

Title

Using query syntax this query is easier,但仍然不如使用虚拟属性那样简单直观。仍然是您要说服老板,使您相信所选择的方法是最好的理解,测试和维护方法

相关问题