Как включить ODATA веб-API ASP.NET в ActiveRecord / NHibernate - PullRequest
0 голосов
/ 05 марта 2012

В ASP.NET Web API он позволяет писать запросы ODATA в строке URL, чтобы указать, какие данные вы хотите вернуть из метода.Однако часть, которую мне трудно понять, заключается в том, что ODATA работает для фильтрации коллекции объектов C # IQueryable, а не самой таблицы базы данных.

Это нецелесообразно, потому что на самом деле вы хотите фильтровать на уровне базы данных, поскольку было бы ужасно возвращать все объекты из базы данных, загружать их в список C # IQueryable, а затем иметь фильтр ODATA, который этот список,

Вот код, который использует NHibernate и Castle Active Record для доступа к данным:

public IQueryable<Message> GetAll()
{
    return from m in MessageData.FindAllQueryable()
           select ConvertToView(m);
}

public static IQueryable<Message> FindAllQueryable()
{
    var criteria = DetachedCriteria.For<Message>()
        .CreateAlias("MessageRecipients", "mr")
        .AddOrder(new Order("Id", false));
    return ActiveRecordMediator<Message>.FindAll(criteria).AsQueryable();
}

Конечным результатом этого кода будет возвращение всех сообщений из базы данных.Как я могу позволить ODATA выполнять свои фильтры на самой базе данных?В противном случае вся эта концепция ODATA нецелесообразна в реальных ситуациях.

Ответы [ 3 ]

2 голосов
/ 06 марта 2012

Имейте в виду, вы имеете дело с IQueryable, который не является физическим списком объектов.Это запрос, который имеет потенциал потенциала , который должен быть выполнен, и в результате получается список объектов.Эти запросы также могут быть объединены в цепочку:

var query = customRepository.Where(x => x.CustomerName == "John"); //no results generated
var query2 = query.Where(x => x.Salary > 100000); // still no results generated
var results = query2.ToList();  // now results are generated

Вы сможете просто вернуть экземпляр Session.Query из NHibernate.Функциональность OData затем объединит дополнительные критерии в зависимости от URL, а затем перечислит результаты обратно.

1 голос
/ 06 марта 2012

Вот как я закончил работать.Огромное спасибо Андреасу за то, что он привел меня к NHibernate.OData.

В своем действии контроллера я получаю данные из URL и передаю их в функцию доступа к данным:

public IQueryable<Message> GetAll(int authUserId, int userId, DateTime? startDate, DateTime? endDate)
        {
            LogWriter.Write(String.Format("Getting all messages for user {0}", userId));

            //get messages and convert to view.
            return from m in MessageData.FindAll(userId, startDate, endDate, GetOData())
                    select new Message(m);
        }

    protected string GetOData()
            {
                var odata = this.Request.RequestUri.Query;
                odata = odata.Substring(odata.IndexOf("$"), odata.Length - odata.IndexOf("$"));
                odata = odata.Replace("%20", " ");
                return odata;
            }

Внутри данныхметод доступа, мы получаем сеанс NHibernate и вызываем session.ODataQuery:

 public static IQueryable<Message> FindAll(int userId, DateTime? startDate, DateTime? endDate, string odata)
            {
                ICriteria query = GetSession().ODataQuery<Message>(odata);
                var detachedCriteria = new ConvertedDetachedCriteria(query)
                    .CreateAlias("MessageRecipients", "mr")
                    .Add(Restrictions.Or(
                        Restrictions.Eq("SenderUserId", userId),
                        Restrictions.Eq("mr.Key.RecipientId", userId)
                    ));
                return FindAllQueryable(detachedCriteria);
            }

    public static ISession GetSession()
            {
                var factory = ActiveRecordMediator.GetSessionFactoryHolder().GetSessionFactories()[0];
                return factory.OpenSession();
            }

public static IQueryable<T> FindAllQueryable(DetachedCriteria criteria)
        {
            return ActiveRecordMediator<T>.FindAll(criteria).AsQueryable();
        }

Кроме того, для преобразования ICriteria в DetachedCriteria необходим простой класс ConvertedDetachedCriteria.

public class ConvertedDetachedCriteria : DetachedCriteria
    {
        public ConvertedDetachedCriteria(ICriteria criteria)
            : base((CriteriaImpl)criteria, criteria)
        {
            var impl = (CriteriaImpl)criteria;
            impl.Session = null;
        }
    }

Надеемся, что так и будетпомогите кому-нибудь еще.Теперь я могу писать запросы odata к моим методам веб-API asp.net и фильтровать их на уровне БД, что гораздо полезнее, чем фильтрация объектов c # !!

0 голосов
/ 15 февраля 2013

Добавляя к ответу @Justin, без ActiveRecord можно просто вернуть что-то вроде

public IQueryable<Message> Get()
{
    ICriteria query = _unitOfWork.CurrentSession.ODataQuery<Message>(GetOData());
    return query.Future<Location>().AsQueryable<Location>();
}

// Taken from @Justin's answer
protected string GetOData()
{
    var odata = this.Request.RequestUri.Query;
    odata = odata.Substring(odata.IndexOf("$"), odata.Length - odata.IndexOf("$"));
    odata = odata.Replace("%20", " ");
    return odata;
}

Это должно поставить вас на тестирование!

...