C# 我可以创建一个用于Linq的助手函数吗?

C# 我可以创建一个用于Linq的助手函数吗?,c#,linq,C#,Linq,我有一个助手函数: namespace PublicationSystem.Tools { public class Format { public static string FullName(string salutation, string first, string middle, string last, string suffix = "")

我有一个助手函数:

namespace PublicationSystem.Tools
{
    public class Format
    {
        public static string FullName(string salutation, 
            string first, 
            string middle, 
            string last, 
            string suffix = "")
        {
            var fullName = new StringBuilder();

            if (!string.IsNullOrEmpty(salutation)) fullName.Append(salutation + " ");

            fullName.Append(first + " ");

            if (!string.IsNullOrEmpty(middle)) fullName.Append(middle.Trim() + " ");

            fullName.Append(last);

            if (!string.IsNullOrEmpty(suffix)) fullName.Append(" " + suffix);

            return fullName.ToString().Trim();
        }
    }
}
我希望在Linq查询中使用它,如下所示:

SessionUser = (
    from pi in db.ProfileIdentifier
    join p in db.Profile on pi.ProfileId equals p.ProfileId
    where
        pi.ProfileIdentifierTypeId == (int)ProfileIdentifierTypes.email &&
        pi.ProfileIdentifierValue == email &&
        pi.IsActive
    select new LoginViewModel
    {
        ProfileId = p.ProfileId,
        SessionId = sessionTokenId,
        FullName = Format.FullName(p.Salutation,p.FirstName,p.MiddleName,p.LastName),
        Email = email,
        Permissions = (
            from ra in db.RoleAssignment
            join rp in db.RolePermission on ra.RoleId equals rp.RoleId
            join perm in db.Permission on rp.PermissionId equals perm.PermissionId
            where ra.AssigneeId == p.ProfileId &&
                rp.IsActive
            select new ProfilePermission
            {
                RoleId = ra.RoleId,
                AssignedToId = ra.AssignedToId,
                PermissionId = perm.PermissionId,
                PermissionName = perm.PermissionName,
                PermissionGroupId = perm.PermissionGroupId
            }).ToList()
    }).FirstOrDefault();

有什么方法可以做到这一点吗?

是的,但是当查询数据源(例如SQL Server)时,该提供程序将不知道如何处理您的函数

您可以在查询中使用,使该查询的其余部分在客户端而不是数据库中进行计算。调用.AsEnumerable()后,可以使用自己的函数,如Format.FullName()

请注意,您应该避免在数据库中完成筛选之前调用.AsEnumerable(),因为调用之后的所有数据都会从数据库传输到客户端程序。

不知道如何将方法的内容
全名(…)
解析为sql

您可以执行查询,返回匿名对象,例如:

var tempUser = (
    from pi in db.ProfileIdentifier
    join p in db.Profile on pi.ProfileId equals p.ProfileId
    where
        pi.ProfileIdentifierTypeId == (int)ProfileIdentifierTypes.email &&
        pi.ProfileIdentifierValue == email &&
        pi.IsActive
    select new 
    {
        p.ProfileId,
        SessionId = sessionTokenId,
        p.Salutation,       
        p.FirstName,
        p.MiddleName,
        p.LastName,
        Email = email
    }).FirstOrDefault();
if (tempUser != null)   
{
    SessionUser = new LoginViewModel
    {
        ProfileId = tempUser.ProfileId,
        SessionId = tempUser.SessionId,
        FullName = Format.FullName(tempUser.Salutation, tempUser.FirstName, tempUser.MiddleName, tempUser.LastName),
        Email = tempUser.Email
    };
}
之后,您可以使用函数
FullName(..)
转换结果,例如:

var tempUser = (
    from pi in db.ProfileIdentifier
    join p in db.Profile on pi.ProfileId equals p.ProfileId
    where
        pi.ProfileIdentifierTypeId == (int)ProfileIdentifierTypes.email &&
        pi.ProfileIdentifierValue == email &&
        pi.IsActive
    select new 
    {
        p.ProfileId,
        SessionId = sessionTokenId,
        p.Salutation,       
        p.FirstName,
        p.MiddleName,
        p.LastName,
        Email = email
    }).FirstOrDefault();
if (tempUser != null)   
{
    SessionUser = new LoginViewModel
    {
        ProfileId = tempUser.ProfileId,
        SessionId = tempUser.SessionId,
        FullName = Format.FullName(tempUser.Salutation, tempUser.FirstName, tempUser.MiddleName, tempUser.LastName),
        Email = tempUser.Email
    };
}

这是最简单的转换:

SessionUser = (
    from pi in db.ProfileIdentifier
    join p in db.Profile on pi.ProfileId equals p.ProfileId
    where
        pi.ProfileIdentifierTypeId == (int)ProfileIdentifierTypes.email &&
        pi.ProfileIdentifierValue == email &&
        pi.IsActive
    select p)
    .ToList()
    .Select(p=>new LoginViewModel
    {
        ProfileId = p.ProfileId,
        SessionId = sessionTokenId,
        FullName = Format.FullName(p.Salutation,p.FirstName,p.MiddleName,p.LastName),
        Email = email
    }).FirstOrDefault();
这将更有效率:

SessionUser = (
    from pi in db.ProfileIdentifier
    join p in db.Profile on pi.ProfileId equals p.ProfileId
    where
        pi.ProfileIdentifierTypeId == (int)ProfileIdentifierTypes.email &&
        pi.ProfileIdentifierValue == email &&
        pi.IsActive
    select p)
    .Take(1)
    .ToList()
    .Select(p=>new LoginViewModel
    {
        ProfileId = p.ProfileId,
        SessionId = sessionTokenId,
        FullName = Format.FullName(p.Salutation,p.FirstName,p.MiddleName,p.LastName),
        Email = email
    }).FirstOrDefault();
SessionUser = (
    from pi in db.ProfileIdentifier
    join p in db.Profile on pi.ProfileId equals p.ProfileId
    where
        pi.ProfileIdentifierTypeId == (int)ProfileIdentifierTypes.email &&
        pi.ProfileIdentifierValue == email &&
        pi.IsActive
    select new 
    {
        p.ProfileId,
        p.Salutation,       
        p.FirstName,
        p.MiddleName,
        p.LastName
    })
    .Take(1)
    .ToList()
    .Select(p=>new LoginViewModel
    {
        ProfileId = p.ProfileId,
        SessionId = sessionTokenId,
        FullName = Format.FullName(p.Salutation,p.FirstName,p.MiddleName,p.LastName),
        Email = email
    }).FirstOrDefault();
更有效的是:

SessionUser = (
    from pi in db.ProfileIdentifier
    join p in db.Profile on pi.ProfileId equals p.ProfileId
    where
        pi.ProfileIdentifierTypeId == (int)ProfileIdentifierTypes.email &&
        pi.ProfileIdentifierValue == email &&
        pi.IsActive
    select p)
    .Take(1)
    .ToList()
    .Select(p=>new LoginViewModel
    {
        ProfileId = p.ProfileId,
        SessionId = sessionTokenId,
        FullName = Format.FullName(p.Salutation,p.FirstName,p.MiddleName,p.LastName),
        Email = email
    }).FirstOrDefault();
SessionUser = (
    from pi in db.ProfileIdentifier
    join p in db.Profile on pi.ProfileId equals p.ProfileId
    where
        pi.ProfileIdentifierTypeId == (int)ProfileIdentifierTypes.email &&
        pi.ProfileIdentifierValue == email &&
        pi.IsActive
    select new 
    {
        p.ProfileId,
        p.Salutation,       
        p.FirstName,
        p.MiddleName,
        p.LastName
    })
    .Take(1)
    .ToList()
    .Select(p=>new LoginViewModel
    {
        ProfileId = p.ProfileId,
        SessionId = sessionTokenId,
        FullName = Format.FullName(p.Salutation,p.FirstName,p.MiddleName,p.LastName),
        Email = email
    }).FirstOrDefault();

看起来不错。但是,我在linq语句中添加了一些代码。我正在做第二个/子查询。我想知道我是否还能这样做?在这里使用
ToList
是一个非常糟糕的主意。您至少应该使用可计算的
aseneumerable
,即使这样也不是最好的。@MKenyonII是的,您仍然可以这样做。只需确保执行.Take(1),将从数据库返回的行数限制为仅1行。将您的权限放在第一个选择中,这样它就可以访问数据库,并在第二个选择中添加
Permissions=p.Permissions
。请按照Servy的建议将.ToList()更改为.AsEnumerable(),尽管在我的系统中,两者之间的差异约为2/10000秒+/-1/10000秒。我不认为这是一个非常糟糕的主意,但最好使用