Как запросить свойства профиля Asp.Net с помощью LINQ

У меня есть свойство профиля Asp.net Profile.Location, Gender и т. Д.

мне нужно получить список всех пользователей, чье местоположение принадлежит "Лондон" и пол = мужской

как выполнить поиск в профиле Asp.net с помощью LINQ


person Bitlancer    schedule 26.05.2011    source источник
comment
мне нужно искать и фильтровать на основе полей профиля. но все значения хранятся в одной строке в таблице aspnet_Profile. и не рекомендуется запрашивать из таблицы aspnet_profile. Я могу использовать ProfileManager.GetAllProfiles (), чтобы получить коллекцию profileInfo. и в основном пытается фильтровать с помощью LINQ   -  person Bitlancer    schedule 26.05.2011
comment
вы не можете выполнять запросы linq к коллекции GetAllProfiles? Если да, то просмотрите programmersunlimited.wordpress.com/2011/01/08/, глядя на MSDN, он показывает, что тип возврата System.Web.Profile.ProfileInfoCollection - это ICollection, IEnumerable, что означает, что вы не получите Linq на нем. Используйте код из ссылки, чтобы получить функциональность Linq.   -  person Dustin Davis    schedule 27.05.2011
comment
Объект ProfileInfo содержит только самую основную информацию, такую ​​как UserName или LastActivityDate, он НЕ содержит настраиваемых полей, определенных в web.config. Таким образом, даже если Linq доступен в Коллекции, он не позволит вам фильтровать ваши настраиваемые поля. Вам нужен метод, который возвращает коллекцию объектов ProfileBase, и ни один из предоставленных методов не позволяет этого.   -  person Julien N    schedule 16.08.2011


Ответы (3)


Собственно, вы можете это сделать. Но сначала вам нужно сделать пару вещей:

  1. Функция, которая анализирует и возвращает сериализованное свойство / значения.
  2. Необязательно представление, которое вызывает функцию для каждой пользовательской строки. Это необязательно, потому что некоторые ORM поддерживают составление запросов с пользовательскими функциями. В любом случае рекомендую поставить вид на место.

Вот написанная мной функция CLR, которая анализирует значения столбцов PropertyNames и PropertyValuesString из таблицы aspnet_Profile. Он возвращает таблицу со столбцом «Свойство» и столбцом «Значение».

using System.Collections;
using System.Collections.Generic;
using System.Data.SqlTypes;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.SqlServer.Server;

public partial class UserDefinedFunctions
{
    private static readonly Regex ProfileRegex = new Regex(@"([a-zA-Z]+):[A-Z]:(\d+):(\d+)");

    [SqlFunction(FillRowMethodName = "FillProfileRow",TableDefinition="Property nvarchar(250), Value nvarchar(2000)")]
    public static IEnumerable ParseProfileString(SqlString names, SqlString values)
    {
        var dict = ProfileRegex
            .Matches(names.Value)
            .Cast<Match>()
            .ToDictionary(
                x => x.Groups[1].Value,
                x => values.Value.Substring(int.Parse(x.Groups[2].Value), int.Parse(x.Groups[3].Value)));

        return dict;
    }

    public static void FillProfileRow(object obj, out string Property, out string Value)
    {
        var x = (KeyValuePair<string, string>) obj;
        Property = x.Key;
        Value = x.Value;
    }
};

Разверните эту функцию, а затем создайте представление для данных профиля вашего пользователя. Вот пример:

CREATE VIEW UsersView
AS

SELECT *
FROM (
    SELECT u.UserId
        ,u.Username
        ,m.Email
        ,f.Property
        ,f.Value
    FROM aspnet_Profile p
    INNER JOIN aspnet_Users u ON p.UserId = u.UserId
    INNER JOIN aspnet_Membership m ON m.UserId = u.Userid
    INNER JOIN aspnet_Applications a ON a.ApplicationId = m.ApplicationId
    CROSS APPLY ParseProfileString(p.PropertyNames, p.PropertyValuesString) f
    WHERE a.ApplicationName = 'MyApplication'
    ) src
pivot(min(value) FOR property IN (
            -- list your profile property names here
            FirstName, LastName, BirthDate
            )) pvt

Вуаля, вы можете запросить представление с помощью SQL или ORM по вашему выбору. Я написал это в Linqpad:

from u in UsersView
where u.LastName.StartsWith("ove") 
select u
person Ronnie Overby    schedule 06.12.2012
comment
Я даю +1, мне нравится мощь Linq и RegEx, которые вы использовали в функции ParseProfileString (). - person bau; 30.10.2014
comment
Спасибо, @bau. Мне нравится мыслить последовательностями и функциями, поэтому мой код в большинстве случаев выглядит так. - person Ronnie Overby; 31.10.2014

Нет, вы не можете сделать это с помощью поставщика профиля ASP.NET по умолчанию (который сохраняет данные профиля в одном строковом поле в базе данных), хотя вы все равно можете сделать это после разделения данных профиля в другой таблице базы данных (что является распространенным подходом. а также сохранить данные вашего профиля в другой таблице и связать ее с таблицей пользователей по умолчанию с помощью ключа GUID пользователя), тогда вы можете использовать LINQ для запроса данных профилей пользователей.

person sherifzain    schedule 28.05.2011

подумайте об использовании чего-то вроде этого:

   matches = 
       matches.Union(
          memberDB.aspnet_Profile
          .Where("it.PropertyValuesString Like @first",
           new ObjectParameter("first", "%<FirstName>%" + firstName + "%</FirstName>%")
           ).Select(p => p.UserId));

Я должен, наверное, упомянуть, что мы создали файл edmx для нашей базы данных членства. Тем не менее, я бы подумал о переносе всей этой интересной информации в ее собственные таблицы в базе данных вашего приложения, когда у вас будет такая возможность.

person mcfea    schedule 23.01.2013