我有两张桌子:
Project(
ProjectID INT,
Name VARCHAR(200),
AssignedUserID INT NULL
)
User(
UserID INT,
LastName VARCHAR(50),
FirstName VARCHAR(50)
)
我使用的是Entity Framework Database-First方法。所以在我的模型中:
Class Project{
public int ProjectID;
public string Name;
public Nullable<int> AssignedUserID;
}
Class User{
public int UserID;
public string LastName;
public string FirstName;
}
我想查询所有PROJECT
及其分配的用户:
SELECT
p.ProjectID,
p.Name,
u.LastName,
u.FirstName
FROM Project p
LEFT JOIN Users u ON u.UserID = p.AssignedUserID
翻译为Linq:
var projectDetails =
from p in context.Project
join u in context.User
on p.AssignedUserID equals u.UserID into lj
from x in lj.DefaultIfEmpty()
select new {
ProjectID = p.ProjectID,
ProjectName = p.Name,
UserLastName = u.LastName,
UserFirstName = u.FirstName
}
但是,我收到了错误:
join子句中某个表达式的类型不正确。 呼叫&#39;加入&#39;
时,类型推断失败
我已经在 int? and int comparison when LEFT OUTER JOIN in Linq issue 上尝试了两种解决方案,但它仍然给我这些错误:
使用解决方案:(int)(p.AssignedUserID ?? default(int))
LINQ to Entities无法识别方法&#39; Int32 ToInt32(Int32)&#39; 方法,并且此方法无法转换为商店表达式。
使用解决方案GetValueOrDefault()
:
LINQ to Entities无法识别方法&#39; Int32 GetValueOrDefault(的Int32)&#39;方法,这个方法无法翻译 进入商店表达。
您如何LEFT JOIN
和Nullable<int>
上的int
?
答案 0 :(得分:7)
当我必须在可空字段上进行加入时,我就会这样做
原Linq:
var projectDetails =
from p in context.Project
join u in context.User
on p.AssignedUserID equals u.UserID into lj
from x in lj.DefaultIfEmpty()
select new {
ProjectID = p.ProjectID,
ProjectName = p.Name,
UserLastName = u.LastName,
UserFirstName = u.FirstName
}
修改后的Linq:
var projectDetails =
from p in context.Project
join u in context.User
on new {User = p.AssignedUserID} equals new {User = (int?)u.UserID} into lj
from x in lj.DefaultIfEmpty()
select new {
ProjectID = p.ProjectID,
ProjectName = p.Name,
UserLastName = x.LastName,
UserFirstName = x.FirstName
}
问题是你正在尝试使用int?加入一个int,它会给你错误信息,将UserId的int转换为可以为null的int,将解决你的问题。
答案 1 :(得分:2)
你实际上做了很多EF应该为你做的工作(这种情况很多,尤其是join
)。
您需要Project
课程的导航属性,而不仅仅是您现在拥有的FK:
编辑:为EF Database-First更新了以下POCO(即使用partial
类)。
// generated code
public partial class Project
{
public int ProjectId { get; set; }
public string Name { get; set; }
public int? AssignedUserId { get; set; }
}
public class User
{
public int UserId { get; set; }
public string LastName { get; set; }
public string FirstName { get; set; }
}
// your code
public partial class Project
{
[ForeignKey("AssignedUserId")]
public User User { get; set; }
}
请注意,每次重新生成partial
类时,您必须记住在Project
类的生成版本上添加partial
关键字,但这仍然更好,因为 - 通过将您的添加保留在单独的partial
类声明 - var projectDetails = from p in context.Projects
select new
{
p.ProjectId,
p.Name,
p.User.LastName,
p.User.FirstName
};
关键字是唯一的,您必须记住在生成的类中进行更改。
所以您的查询只是以下内容:
Console.WriteLine(projectDetails.ToString());
让我们看看它是什么样的:
SELECT
[Extent1].[ProjectId] AS [ProjectId],
[Extent1].[Name] AS [Name],
[Extent2].[LastName] AS [LastName],
[Extent2].[FirstName] AS [FirstName]
FROM [Projects] AS [Extent1]
LEFT OUTER JOIN [Users] AS [Extent2] ON [Extent1].[AssignedUserId] = [Extent2].[UserId]
这会产生以下SQL:
{{1}}
这似乎正是你想要的。
答案 2 :(得分:1)
如果联接中的任何列属于Nullable
类型,我们需要使用.Value
获取itts实际值,如下所示: -
join u in context.User
on p.AssignedUserID.Value equals u.UserID into lj
或者您也可以这样做: -
join u in context.User
on new { p.AssignedUserID } equals new { AssignedUserID = u.UserID } into lj