我是Linq的新手,正在使用新的MVC网站进行测试。我仍在努力学习语法和功能,但我遇到了一个我无法解决的问题。任何帮助将不胜感激。
情况:
1 - 我有一个SQL数据库设置来使用默认的ASPNET成员资格提供程序。标准命名约定仍然存在(aspnet_Users,aspnet_Roles,aspnet_UsersInRoleetc。)
2 - 我有一个名为Users的附加表,它提供了扩展的用户信息。 FK是aspnet_User UserId(一对一)。
3 - 我有一个名为Customers的附加表,它提供客户(订购)信息。 FK是Users表中的UserId(一对一)。
4 - 我添加了一个名为CustomerAddress的表格,它提供了客户地址信息。 FK是Customers表中的CustomerId(一对多)。
5 - 我已经设置了一个模型来处理向管理员提供此信息的信息
的问题:
1 - 我希望在此演示模型中包含应用程序中可用的所有角色的列表,以及用户当前是否已分配到该角色。
2 - 我想在此演示模型中包含与用户相关的所有地址的列表
3 - 我无法弄清楚如何使用Linq查询将此信息恢复到我的演示模型
这是我的演示模型(请注意,我目前拥有角色的属性,但我无法弄清楚如何获取此信息。而且......我不确定应该是什么类型的?
namespace Lambuth.PresentationModels.ManageUsers
{
public class UserDetail
{
[Editable(false)]
[Key, ScaffoldColumn(false)]
[Display(Name="User ID")]
public Guid UserId { get; set; }
[Required]
[Editable(false)]
[StringLength(16)]
[Display(Name="User Name")]
public string UserName { get; set; }
[Editable(false)]
[ScaffoldColumn(false)]
[StringLength(16)]
[Display(Name = "Lowered User Name")]
public string LoweredUserName { get; set; }
[Required]
[Editable(false)]
[StringLength(256)]
[Display(Name = "Email")]
public string Email { get; set; }
[Editable(false)]
[ScaffoldColumn(false)]
[StringLength(256)]
[Display(Name = "Lowered Email")]
public string LoweredEmail { get; set; }
[Editable(false)]
[StringLength(16)]
[Display(Name = "Site Alias")]
public string SiteAlias { get; set; }
[Required]
[Editable(false)]
[Display(Name = "Is Approved")]
public bool IsApproved { get; set; }
[Required]
[Editable(false)]
[Display(Name = "Is Locked Out")]
public bool IsLockedOut { get; set; }
[Editable(false)]
[Display(Name = "Join Date")]
public DateTime JoinDate { get; set; }
[Editable(false)]
[Display(Name = "Full Name")]
public string FullName
{
get
{
AccountInfoHelpers help = new AccountInfoHelpers();
return help.GetFullName(this.Salutation, this.FirstName, this.LastName);
}
set {/*no implmentation*/}
}
[Editable(false)]
[StringLength(20)]
[Display(Name = "Salutation")]
public string Salutation { get; set; }
[Editable(false)]
[StringLength(50)]
[Display(Name = "First Name")]
public string FirstName { get; set; }
[Editable(false)]
[StringLength(50)]
[Display(Name = "Last Name")]
public string LastName { get; set; }
[Editable(false)]
[Display(Name = "Last Login Date")]
public DateTime LastLoginDate { get; set; }
[Editable(false)]
[Display(Name = "Assigned Roles")]
public virtual ICollection<UserRole> AssignedRoles { get; set; }
} }
这是我目前拥有的Linq查询:
using (LambuthEntities context = new LambuthEntities())
{
var user = (from u in context.aspnet_Users
join p in context.aspnet_Membership on u.UserId equals p.UserId
join ux in context.Users on u.UserId equals ux.user_id
join c in context.Customers on ux.user_id equals c.user_id
where (ux.user_id == userId) //userId passed in as param
select new UserDetail
{
UserId = ux.user_id,
UserName = u.UserName,
SiteAlias = ux.site_alias,
Email = p.Email,
Salutation = c.salutation,
FirstName = c.first_name,
LastName = c.last_name,
LastLoginDate = p.LastLoginDate,
IsApproved = p.IsApproved,
IsLockedOut = p.IsLockedOut
}).Single();
return user;
}
我在这里走在正确的轨道上吗?任何建议将不胜感激。
谢谢。
答案 0 :(得分:0)
我会对Linq声明略有不同。虽然LinqToSql可用于生成SQL语句,并且能够看起来像SQL语句(如您的示例所示),但我倾向于从生成的对象的角度使用它们。
我的意思是,这不是自己处理表之间的连接,而是利用LinqToSql生成器已经完成的工作并使用它们的对象。业务对象已具有链接到相关对象的属性。
以下是我将如何处理您的linq声明:
var user = (from u in context.aspnet_Users
where (ux.user_id == userId) //userId passed in as param
select new UserDetail
{
UserId = u.user_id,
UserName = u.UserName,
SiteAlias = u.User.site_alias,
Email = u.aspnet_Membership.Email,
Salutation = u.User.Customer.salutation,
FirstName = u.User.Customer.first_name,
LastName = u.User.Customer.last_name,
LastLoginDate = u.aspnet_Membership.LastLoginDate,
IsApproved = u.aspnet_Membership.IsApproved,
IsLockedOut = u.aspnet_Membership.IsLockedOut,
AssignedRoles = u.aspnet_Roles.Select(r => r.RoleName).ToList()
}).Single();
我不确定UserRole类是什么样的,所以我现在只有一个字符串集合。此外,没有您拥有的特定SQL方案(您已设置的属性),我对您对象关系的描述不感兴趣。
此外,在处理从多个表中提取数据的LinqToSQL语句时,您需要确保尽可能少地进行数据库调用。如果不这样做,您可以遇到SELECT n+1 problem。帮助解决此问题的一种方法是LinqToSql中的DataLoadOptions。