如何 select 记录回外键
how to select records back on foreign keys
我正在尝试 select 记录来自 table 的记录,这些记录与单个记录匹配相同的外键。我写了以下 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)
我在entity framework里也写了同样的东西,但是写了两行,但我想知道是否还有更好、更优化的方法?
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 });
如有任何帮助,我们将不胜感激。
遗憾的是您忘了给我们您的 类 和规格!
在尝试了解你的 SQL 之后,似乎 table1
有一个 AssetStructureId
,它是 Table2
的外键 Table1
属于。可能是一对多关系。
Table2
有一个外键 Table3Id
到你的 Table2
所属的 Table3
,也是一对多关系
最后 Table3
有一个外键 Table4Id
到 Table3
所属的 Table4
。
我的天,您确实喜欢标识符的专有名称,不是吗?
所以:
- 每个
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;}
...
}
In entity framework the columns of your tables are represented by
non-virtual properties; the virtual properties represent the relations
between the tables.
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;}
}
这就是 entity framework 确定 table 的名称和列以及 table 之间的关系所需的全部内容。如果出于某种原因您想要不同的 table 名称或列,则需要添加属性或使用流畅的 API.
最重要的是你的虚拟属性是正确的。
无论何时你使用虚拟属性,entity framework都知道需要(组)加入并会为您完成
现在我们已经定义了您的四个 table,我们可以开始了
回到你的问题
糟糕,您忘记指定您想要的内容 select!
显然你的四个 table 之一有一个 Title
。虽然你没说,但我认为Title
是Table1
的属性。看起来你有 Table1Element
的 Id
你想要 select 拥有这个 Table1Element
[=50 的 Table4
的 Title
=]
输入:RequestedId
= 21803
- Id 为 A 的 Table4Element 有一个
Title
- 具有外键的 Table3Element Table4ElementId A 具有 ID B
- 带外键的 Table2Element Table3ElementId B 的 ID C
- 带外键的 Table1Element Table3ElementId C 的 ID 为 21803
你想要Title
.
使用虚拟属性使查询变得简单。 Entity Framework 将为您进行连接:
int requestedId = 21803;
var requestedTitle = myDbContext.Table1Elements // from all Table1 elements
.Where(table1Element => table1Element.Id = requestedId) // keep the one with the requestedId
.Select(table1Element = table1Element // and select the Title
.Table2Element // of the Table4 element
.Table3element // that it belongs to
.Table4Element
.Title)
.FirstOrDefault(); // You know there is only one
非常直观易懂。
我不知道为什么,但有些人坚持自己进行连接。使用方法语法与四个 tables 的连接看起来很可怕:
int requestedId = 21803;
var requestedTitle = myDbContext.Table1Elements // from all Table1Elements
.Where(table1Element => table1Element.Id = requestedId) // keep the one with the requestedId
.Join(myDbContext.Table2Elements, // join with Table2Elements
table1Element => table1Element.Table2ElementId, // from Table1 take the foreign key
table2Element => table2Element.Id, // from Table2 take the primary key
(table1Element, table2Element) => table2Element) // when they match keep the Table2
.Join(myDbContext.Table3Elements, // to join with Table3
table2Element => table2Element.Table3ElementId, // foreign key to Table3
table3Element => table3Element.Id, // primary key
(table2Element, table3Element) => table3Element) // keep table3Element
.Join(myDbContext.Table4Elements, // to join with Table4
table3Element => table3Elemen.Table4ElementId, // foreign key
table4Element => table4Element.Id, // primary key
(table3Element, table4Element) => table4Element.Title) // keep the Title
.FirstOrDefault(); // expect only one element
,但仍然不如使用虚拟属性简单直观。仍然是你说服你的老板,你select的方法是最好理解、测试和维护的
我正在尝试 select 记录来自 table 的记录,这些记录与单个记录匹配相同的外键。我写了以下 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)
我在entity framework里也写了同样的东西,但是写了两行,但我想知道是否还有更好、更优化的方法?
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 });
如有任何帮助,我们将不胜感激。
遗憾的是您忘了给我们您的 类 和规格!
在尝试了解你的 SQL 之后,似乎 table1
有一个 AssetStructureId
,它是 Table2
的外键 Table1
属于。可能是一对多关系。
Table2
有一个外键 Table3Id
到你的 Table2
所属的 Table3
,也是一对多关系
最后 Table3
有一个外键 Table4Id
到 Table3
所属的 Table4
。
我的天,您确实喜欢标识符的专有名称,不是吗?
所以:
- 每个
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;}
...
}
In entity framework the columns of your tables are represented by non-virtual properties; the virtual properties represent the relations between the tables.
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;}
}
这就是 entity framework 确定 table 的名称和列以及 table 之间的关系所需的全部内容。如果出于某种原因您想要不同的 table 名称或列,则需要添加属性或使用流畅的 API.
最重要的是你的虚拟属性是正确的。
无论何时你使用虚拟属性,entity framework都知道需要(组)加入并会为您完成
现在我们已经定义了您的四个 table,我们可以开始了
回到你的问题
糟糕,您忘记指定您想要的内容 select!
显然你的四个 table 之一有一个 Title
。虽然你没说,但我认为Title
是Table1
的属性。看起来你有 Table1Element
的 Id
你想要 select 拥有这个 Table1Element
[=50 的 Table4
的 Title
=]
输入:RequestedId
= 21803
- Id 为 A 的 Table4Element 有一个
Title
- 具有外键的 Table3Element Table4ElementId A 具有 ID B
- 带外键的 Table2Element Table3ElementId B 的 ID C
- 带外键的 Table1Element Table3ElementId C 的 ID 为 21803
你想要Title
.
使用虚拟属性使查询变得简单。 Entity Framework 将为您进行连接:
int requestedId = 21803;
var requestedTitle = myDbContext.Table1Elements // from all Table1 elements
.Where(table1Element => table1Element.Id = requestedId) // keep the one with the requestedId
.Select(table1Element = table1Element // and select the Title
.Table2Element // of the Table4 element
.Table3element // that it belongs to
.Table4Element
.Title)
.FirstOrDefault(); // You know there is only one
非常直观易懂。
我不知道为什么,但有些人坚持自己进行连接。使用方法语法与四个 tables 的连接看起来很可怕:
int requestedId = 21803;
var requestedTitle = myDbContext.Table1Elements // from all Table1Elements
.Where(table1Element => table1Element.Id = requestedId) // keep the one with the requestedId
.Join(myDbContext.Table2Elements, // join with Table2Elements
table1Element => table1Element.Table2ElementId, // from Table1 take the foreign key
table2Element => table2Element.Id, // from Table2 take the primary key
(table1Element, table2Element) => table2Element) // when they match keep the Table2
.Join(myDbContext.Table3Elements, // to join with Table3
table2Element => table2Element.Table3ElementId, // foreign key to Table3
table3Element => table3Element.Id, // primary key
(table2Element, table3Element) => table3Element) // keep table3Element
.Join(myDbContext.Table4Elements, // to join with Table4
table3Element => table3Elemen.Table4ElementId, // foreign key
table4Element => table4Element.Id, // primary key
(table3Element, table4Element) => table4Element.Title) // keep the Title
.FirstOrDefault(); // expect only one element