Is there a ODATA query to linq where expression (ODATA to Linq ) - linq

Basically,
I would like to convert odata query expression "$filter", "itemID eq 1" to where(w=>w.itemID==1)
Is there a ready library for this operation? Otherwise I need to code it by using DynamicLinq classes and linqKit.

I'm using Microsoft WebAPI with the following NuGet packages installed:
http://nuget.org/packages/Microsoft.Data.OData/
http://nuget.org/packages/microsoft.aspnet.webapi.odata
Which lets me write things like:
using System.Web.Http;
using System.Web.Http.OData.Query;
// Some stuff left out
[Queryable]
public IQueryable<Item> Get(ODataQueryOptions<Item> query)
{
var items = query.ApplyTo(from item in context.Items select item);
return (IQueryable<Item>) items;
}
Then I can call it using jQuery Ajax (for the sake of the example, I prefer to use BackboneJS) like this:
$.ajax({ url: '/api/items', data: $.param({ '$filter': 'ID eq 1' }) });
Which will then return only the items with an ID equal to 1, which I think is what you are after?
If itemID is the main ID of the object you are retrieving, I would probably follow REST principles and create and API where the url to retrieve an item with the ID of 1 would be:
/api/items/1
And only use oData queries on the collection of items if I was querying based on other properties of the items in the collection, or do something like below for example when retrieving the top 10 records.
$.ajax({ url: '/api/items', data: $.param({ '$top': 10 }) });

You can use following NuGet package to apply filter:
https://www.nuget.org/packages/Community.OData.Linq
Code sample would be:
using System.Linq;
using Community.OData.Linq;
// dataSet in this example - any IQuerable<T>
Sample[] filterResult = dataSet.OData().Filter("Id eq 2 or Name eq 'name3'").ToArray();
Currently supported: filter and orderby in v4 format

You Can use Microsoft.Rest.Azure.OData
string filter = new ODataQuery(x => x.itemID == 1).Filter;

Related

RethinkDB Thinky - rows within 1 hour

r.db('dbname').table('urls').filter(function(url) {
return url("expires_at").date().eq(r.now().date())
.and(url("expires_at").hours().eq(r.now().hours().sub(1)))
});
I am trying to write the equivalent query using thinky ORM for node.js
I've never worked with Thinky, but according to docs, you should create model and make query on it.
1) Create model. I don't know what documents you are storing in Rethink. But something like this:
var thinky = require('thinky')();
var type = thinky.type;
// Create a model
var Urls = thinky.createModel("urls", {
id: String,
expires_at: Date
// another fields if needed
});
2) Query:
Don't know actual syntaxes for filter in Thinky, but somehting like this:
Urls.filter(function(url) {
return url("expires_at").date().eq(r.now().date())
.and(url("expires_at").hours().eq(r.now().hours().sub(1)))
}).then(function(result) {
// result is an array of instances of `Urls `
});

Returning an odata IQueryable object that differs to the query options

I need to get the following code to work
public IQueryable<BankingDTO> Get(ODataQueryOptions<TillSummaryDTO> options)
{
return((IQueryable<BankingDTO>)options.ApplyTo(this._bankingService.GetBanking()));
}
I would like to query on TillSummaryDTO because it has the field "TillOpID" on it. However I would like to return BankingDTO as this is the end result which contains the group by and sum. When I run the query I receive the error "Cannot apply ODataQueryOptions of 'Bepoz.Presentation.ViewModels.TillSummaryDTO' to IQueryable of 'Bepoz.Presentation.ViewModels.BankingDTO" what is the best practice for this?
The bankingservice.GetBanking method looks like this
var query = from t in _tillSummaryRepository.Table
join w in _workStationRepository.Table on t.TillOpID equals w.WorkstationID
join s in _storeRepository.Table on w.StoreID equals s.StoreID
join v in _venueRepository.Table on s.VenueID equals v.VenueID
select new TillSummaryDTO
{
TillOpID = t.TillOpID,
Cash = t.Cash,
Workstation = new WorkstationDTO()
{
WorkstationID = w.WorkstationID,
Name = w.Name,
Store = new StoreDTO()
{
StoreID = s.StoreID,
StoreGroup = s.StoreGroup,
Name = s.Name,
Venue = new VenueDTO()
{
VenueID = v.VenueID,
VenueGroup = v.VenueGroup,
Name = v.Name,
}
}
}
};
return query.GroupBy(x => x.Workstation.Name)
.Select(x => new BankingDTO()
{
TotalCash = x.Sum(y => y.Cash),
WorkstationName = x.Key
});
The scenario you want to achieve is that you have an entity set of TillSummaryDTO that you want to query, and you would like the return type to be a collection of BankingDTO. The query for the BankingDTO is carried out by applying the query options in the URL onto TillSummaryDTO . But the fact that the BankingDTO and TillSummaryDTO are different kind of types makes it impossible achieve that in a simple Get action method, right?
This scenario can be better resolved by the function feature of the OData protocol that the function takes the TillSummaryDTO collection as input parameter, has some internal complicated logic to query for the right BankingDTO, and returns the BankingDTO instead of TillSummaryDTO.
For the concept of function in OData protocol, you can refer to this link for V4 and section "10.4.2. Functions" of this page for V3.
For implementation, this sample can be referred to for Web API OData V4 and this tutorial can be referred to for Web API OData V3.

LINQ to Entities does not recognize the method 'Boolean CheckMeetingSettings(Int64, Int64)' method

I am working with code first approach in EDM and facing an error for which I can't the solution.Pls help me
LINQ to Entities does not recognize the method 'Boolean
CheckMeetingSettings(Int64, Int64)' method, and this method cannot be
translated into a store expression.
My code is following(this is the query which I have written
from per in obj.tempPersonConferenceDbSet
where per.Conference.Id == 2
select new PersonDetials
{
Id = per.Person.Id,
JobTitle = per.Person.JobTitle,
CanSendMeetingRequest = CheckMeetingSettings(6327,per.Person.Id)
}
public bool CheckMeetingSettings(int,int)
{
///code I have written.
}
Please help me out of this.
EF can not convert custom code to SQL. Try iterating the result set and assigning the property outside the LINQ query.
var people = (from per in obj.tempPersonConferenceDbSet
where per.Conference.Id == 2
order by /**/
select new PersonDetials
{
Id = per.Person.Id,
JobTitle = per.Person.JobTitle,
}).Skip(/*records count to skip*/)
.Take(/*records count to retrieve*/)
.ToList();
people.ForEach(p => p.CanSendMeetingRequest = CheckMeetingSettings(6327, p.Id));
With Entity Framework, you cannot mix code that runs on the database server with code that runs inside the application. The only way you could write a query like this, is if you defined a function inside SQL Server to implement the code that you've written.
More information on how to expose that function to LINQ to Entities can be found here.
Alternatively, you would have to call CheckMeetingSettings outside the initial query, as Eranga demonstrated.
Try:
var personDetails = obj.tempPersonConferenceDbSet.Where(p=>p.ConferenceId == 2).AsEnumerable().Select(p=> new PersonDetials
{
Id = per.Person.Id,
JobTitle = per.Person.JobTitle,
CanSendMeetingRequest = CheckMeetingSettings(6327,per.Person.Id)
});
public bool CheckMeetingSettings(int,int)
{
///code I have written.
}
You must use AsEnumerable() so you can preform CheckMeetingSettings.
Linq to Entities can't translate your custom code into a SQL query.
You might consider first selecting only the database columns, then add a .ToList() to force the query to resolve. After you have those results you van do another select where you add the information from your CheckMeetingSettings method.
I'm more comfortable with the fluid syntax so I've used that in the following example.
var query = obj.tempPersonConferenceDbSet
.Where(per => per.Conference.Id == 2).Select(per => new { Id = per.Person.Id, JobTitle = per.Person.JobTitle })
.ToList()
.Select(per => new PersonDetails { Id = per.Id,
JobTitle = per.JobTitle,
CanSendMeetingRequest = CheckMeetingSettings(6327, per.Person.Id) })
If your CheckMeetingSettings method also accesses the database you might want to consider not using a seperate method to prevent a SELECT N+1 scenario and try to express the logic as part of the query in terms that the database can understand.

Why am I getting a MissingMethodException with querying the TableServiceContext?

I am trying to query a Azure Table Storage. For that I use the following two methods:
TableServiceContext:
public IQueryable<T> QueryEntities<T>(string tableName) where T : TableServiceEntity
{
this.ResolveType = (unused) => typeof(T);
return this.CreateQuery<T>(tableName);
}
Code that uses the method above:
CloudStorageAccount account = AzureConnector.GetCloudStorageAccount(AppSettingsVariables.TableStorageConnection);
AzureTableStorageContext context = new AzureTableStorageContext(account.TableEndpoint.ToString(), account.Credentials);
// Checks if the setting already exists in the Azure table storage. Returns null if not exists.
var existsQuery = from e in context.QueryEntities<ServiceSettingEntity>(TableName)
where e.ServiceName.Equals(this.ServiceName) && e.SettingName.Equals(settingName)
select e;
ServiceSettingEntity existingSettginEntity = existsQuery.FirstOrDefault();
The LINQ query above generates the following request url:
http://127.0.0.1:10002/devstoreaccount1/PublicSpaceNotificationSettingsTable()?$filter=(ServiceName eq 'PublicSpaceNotification') and (SettingName eq 'expectiss')
The code in the class generates the following MissingMethodException:
I have looked at the supported LINQ Queries for the Table API;
Looked at several working stackoverflow solutions;
Tried IgnoreResourceNotFoundException on the TableServiceContext (usercomments of QueryOperators);
Tried to convert the linq query with ToList() before calling first or default (usercomments of QueryOperators).
but I can't get this to work.
Make sure you have parameterless constructor for the class "ServerSettingEntity". The ‘DTO’ that inherits TableServiceEntity needs a constructor with no parameters.

MvcContrib Grid Sorting

Am testing out MvcContrib's grid for sorting.
Am using LightSpeed as my ORM
Problem: getting compile error on: listOfRfidTags = ...
The type arguments for method 'System.Linq.Enumerable.OrderBy(System.Collections.Generic.IEnumerable, System.Func, System.Collections.Generic.IComparer)' cannot be inferred from the usage. Try specifying the type arguments explicitly.
public ActionResult Index(GridSortOptions sort)
{
IEnumerable<RfidTag> listOfRfidTags = uow.RfidTags;
if(sort.Column != null) {
listOfRfidTags = listOfRfidTags.OrderBy(sort.Column, sort.Direction);
}
ViewData["sort"] = sort;
return View(listOfRfidTags);
}
view:
#Html.Grid(Model).Columns(column =>{
column.For(a => Html.ActionLink("Edit", "Edit", new { id = a.Id })).Named("Edit");
column.For(a => a.TagCode).Named("TagCode").Sortable(true);
column.For(a => a.Number);
})
You are getting this compiling error because you are trying to use an OrderBy extension method that is only defined in MvcContrib and not in System.Linq.
In order to fix it, you just need to use the following line:
using MvcContrib.Sorting;
And then you can use the OrderBy method as in your original code:
listOfRfidTags = listOfRfidTags.OrderBy(sort.Column, sort.Direction);
Although itowlson answer works, he just reimplements what the OrderBy extension method in MvcContrib already does (see SortExtensions.cs).
The OrderBy extension method takes a delegate for getting the sort key, not a column and direction. So this line:
listOfRfidTags = listOfRfidTags.OrderBy(sort.Column, sort.Direction);
needs to look something like this:
listOfRfidTags = listOfRfidTags.OrderBy(r => r.SomeProperty);
(or OrderByDescending depending on the sort.Direction). The trouble is that SomeProperty can't be determined at compile time because you want it to come from sort.Column. This means that if you want to use LINQ then you'll probably need to use Dynamic LINQ or Reflection to extract the property you want to sort on e.g.
PropertyInfo property = typeof(RfidTag).GetProperty(sort.Column);
listOfRfidTags = listOfRfidTags.OrderBy(r => property.GetValue(r));
However, since you are using LightSpeed as your ORM, you can bypass LINQ and use the core API, which does allow dynamic column names:
Order order = Order.By(sort.Column);
if (sort.Direction == SortDirection.Descending))
order = order.Descending();
IList<RfidTag> listOfRfidTags = uow.Find<RfidTag>(new Query { Order = order });
This has the side benefit that the sorting will happen on the database instead of in the Web application.

Resources