Linq to sql 如何在Linq to SQL导航属性生成的查询中使用左键而不是内部联接
当我从Linq to SQL中的父对象中进行选择时,我将获得父表中的所有记录。但是,当我同时选择导航属性时(从具有1:1关系和共享主键的扩展表中),我只会得到填充了该导航属性的记录。如何使用navigation属性从父级获取所有记录,而不管是否填充了子级?(即左连接而不是内连接)?Linq到SQL导航属性可以做到这一点吗,或者手动连接是唯一的选项吗?关于的一个建议答案说这应该是可能的,并说实体框架将处理它,但我无法让它与Linq to SQL一起工作 查询:Linq to sql 如何在Linq to SQL导航属性生成的查询中使用左键而不是内部联接,linq-to-sql,left-join,inner-join,navigation-properties,Linq To Sql,Left Join,Inner Join,Navigation Properties,当我从Linq to SQL中的父对象中进行选择时,我将获得父表中的所有记录。但是,当我同时选择导航属性时(从具有1:1关系和共享主键的扩展表中),我只会得到填充了该导航属性的记录。如何使用navigation属性从父级获取所有记录,而不管是否填充了子级?(即左连接而不是内连接)?Linq到SQL导航属性可以做到这一点吗,或者手动连接是唯一的选项吗?关于的一个建议答案说这应该是可能的,并说实体框架将处理它,但我无法让它与Linq to SQL一起工作 查询: TestDataCo
TestDataContext repository = new TestDataContext();
// No navigation property selected, returns all records from Persons
var result = repository.Persons.Select(x => new { x.PersonID, x.Name });
// Navigation property selected, returns only persons having a record in PersonExtensions table
var result1 = repository.Persons.Select(x => new { x.PersonID, x.Name, x.Extension.Height });
以下是域类:
[Table(Name = "Persons")]
public class Person
{
private System.Data.Linq.EntityRef<PersonExtension> _extension = new System.Data.Linq.EntityRef<PersonExtension>();
[Association(Name = "Persons_PersonExtensions", Storage = "_extension", ThisKey = "PersonID", OtherKey = "PersonID", IsForeignKey = true)]
public PersonExtension Extension
{
get
{
return _extension.Entity;
}
set
{
_extension.Entity = value;
}
}
[Column(Name = "PersonID", DbType = "int NOT NULL IDENTITY", IsPrimaryKey = true, IsDbGenerated = true, CanBeNull = false, UpdateCheck = System.Data.Linq.Mapping.UpdateCheck.Never)]
public int PersonID { get; set; }
[Column(Name = "Name")]
public string Name { get; set; }
[Column(Name = "Gender")]
public string Gender { get; set; }
}
[Table(Name = "PersonExtensions")]
public class PersonExtension
{
private System.Data.Linq.EntityRef<Person> _person = new System.Data.Linq.EntityRef<Person>();
[Association(Name = "Persons_PersonExtensions", Storage = "_person", ThisKey = "PersonID", OtherKey = "PersonID", IsForeignKey = true)]
public Person Person
{
get
{
return _person.Entity;
}
set
{
_person.Entity = value;
}
}
[Column(Name = "PersonID", DbType = "int NOT NULL", IsPrimaryKey = true, CanBeNull = false, UpdateCheck = System.Data.Linq.Mapping.UpdateCheck.Never)]
public int PersonID { get; set; }
[Column(Name = "Height ")]
public int? Height { get; set; }
}
任何帮助都将不胜感激
注意:上面的问题已从原来的问题稍作修改,以便更清楚地说明其目的是使用导航属性。将zzz替换为高度类型
var result1 = repository.Persons.Select(x =>
new { x.PersonID, x.Name, x.Extension == null ? (zzz?)null : x.Extension.Height });
更新 基于:
看起来Linq到SQL导航属性中的左连接是可能的,但是对象不能像我设置我的那样设置。相反,“扩展”表的id必须不同于“主”表的id,“主”表必须包含对扩展表id的可空引用(例如int?)。事实上,这个变量是可以为null的,它告诉Linq to SQL创建一个左连接,而不是一个内部连接。当然,如果我尝试在两个表中使用相同的键,那是不可能的,因为主表的id必须是该表中不可为null的字段 我是根据我的经验得出这个结论的
不幸的是,这也很混乱,但我非常确定,如果我想调用导航属性来生成左连接,这是唯一的选择。Hmm。我刚刚尝试过-将查询行更改为以下内容(命名为匿名类型的Height变量),但我仍然只得到结果集中PersonExtensions中存在的记录:var result1=repository.Persons.Select(x=>new{x.PersonID,x.Name,Height=x.Extension==null?(int?)null:x.Extension.Height});不幸的是,仍然只有两个表中存在的一条记录返回。@user756366就这样。谢谢!这确实有效。不幸的是,我想我确实需要让这个问题保持开放。。。因为我真正期待的是一种使用导航属性并让linq自动生成左连接的方法。相反,此解决方案会忽略导航属性并手动创建联接,这在许多情况下都可以工作,但很难与动态SQL和用户生成的查询一起使用。我非常感谢你的帮助!非常感谢你!抱歉,无法标记为答案!你有不可为空的ID?天哪,怪不得它对你不起作用。我完全不明白为什么可以对另一个表进行可为空的逻辑引用,但仍然是不可为空的ID字段。这没有任何意义,表明存在一个非常巨大的设计问题。我们希望这样做,因为我们有一个主表已经存在很长时间了,我们希望添加一个扩展表,其中包含更多字段,每个客户自定义,以允许他们添加他们需要的字段。我们关心的是强制执行一条规则,即对于原始表中的每条记录,该表中都必须有一条记录,因为这是一个复杂的现有系统,虽然我们确实计划捕获所有插入记录的位置,但我们不能100%确定是否能够捕获所有位置。我们希望更改不会有丢失现有报告/查询中记录的风险。
CREATE TABLE [dbo].[Persons](
[PersonID] [int] IDENTITY(1,1) NOT NULL,
[Name] [nvarchar](50) NULL,
[Gender] [nchar](10) NULL,
CONSTRAINT [PK_Persons] PRIMARY KEY CLUSTERED
(
[PersonID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
CREATE TABLE [dbo].[PersonExtensions](
[PersonID] [int] NOT NULL,
[Height] [int] NULL,
CONSTRAINT [PK_PersonExtensions] PRIMARY KEY CLUSTERED
(
[PersonID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[PersonExtensions] WITH CHECK ADD CONSTRAINT [FK_PersonExtensions_Persons] FOREIGN KEY([PersonID])
REFERENCES [dbo].[Persons] ([PersonID])
GO
ALTER TABLE [dbo].[PersonExtensions] CHECK CONSTRAINT [FK_PersonExtensions_Persons]
GO
var result1 = repository.Persons.Select(x =>
new { x.PersonID, x.Name, x.Extension == null ? (zzz?)null : x.Extension.Height });
var query = from person in repository.Persons
join extension in repository.Extensions
on person.ExtensionId equals extension.ExtensionId into g
from x in g.DefaultIfEmpty() // Creates a LEFT OUTER JOIN.
select new
{
person.PersonID,
person.Name,
Height = x == null ? (int?) : x.Height
};
var result = query.ToArray();