我正在尝试从表中选择与单个记录匹配相同外键的记录记录。我编写了以下有效的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 });
任何帮助将不胜感激。
答案 0 :(得分:0)
您真可惜忘记给我们提供您的课程和规格!
尝试理解您的SQL之后,看来table1
有一个AssetStructureId
,这是Table2
所属的Table1
的外键。可能是一对多关系。
Table2
具有Table3Id
所属Table3
的外键Table2
,也是一对多关系
最后,Table3
对Table4Id
所属的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;}
...
}
在实体框架中,表的列由 非虚拟性质;虚拟属性代表关系 在表之间。
Table2
和Table1
相似:
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
。尽管您没有这么说,但我认为Title
是Table1
的属性。似乎您要从Id
的{{1}}中选择拥有此Table1Element
的{{1}}的{{1}}
输入:Title
= 21803
Table4
您想要Table1Element
。
使用虚拟属性使查询变得简单。实体框架将为您执行联接:
RequestedId
非常直观且易于理解。
我不知道为什么,但是有些人坚持自己做连接。使用方法语法将四个表连接起来看起来很可怕:
Title
Using query syntax this query is easier,但仍然不如使用虚拟属性那样简单直观。仍然是您要说服老板,使您相信所选择的方法是最好的理解,测试和维护方法