no supported translation to sql error? - c#

I am using linq to sql. I am running a query which uses a function to return the right record. I am using a function so I can use if statement which I dont know how to do it within the linq clause. The code is copied below. It returns an error: "GetPageOwner(int 32) has no supported translation to sql" what am i doing wrong? How to fix it to get the same results?
return (from page select new Result
{
pageOwner = GetPageOwner(page.page_id)
});
public Post GetPageOwner(int pageid)
{
var posts = (from dp in db.Posts where dp.pageid == pageid select dp);
var returned = posts;
if (posts.Count() > 0)
{
var latest = posts.OrderByDescending(o => o.Date).FirstOrDefault();
var sharedsamedayaslatest = (from p in posts where p.Date.AddDays(1) >= latest.Date select p);
if (sharedsamedayaslatest.Count() > 1)
{
var followedpost = (from p in posts from s in db.Subscriptions where s.Subscriber == UID && s.Subscribedto == p.UserId select p);
var count = followedpost.Count();
if (count == 1)
{
returned = followedpost;
}
else if (count > 1)
{
returned = (from s in followedpost let reposts = GetPostReposts(s.id) let rating = GetPostRating(s.id) let score = reposts + rating orderby score descending select s);
}
else
{
//no follower shared this post so return the most liked
returned = (from s in sharedsamedayaslatest let reposts = GetPostReposts(s.id) let rating = GetPostRating(s.id) let score = reposts + rating orderby score descending select s);
}
}
else
{
//no shares on the day the latest share
returned = sharedsamedayaslatest;
}
}
else
{
//only one post
returned = posts;
}
return returned.FirstOrDefault(); //order by userid gets a random one
}

Linq to sql has to translate functions from .net into sql. Not all .net functions have an equivalent in sql, and ones written by you definitely don't have one.
That being said you can implement your function as a stored procedure and use it in your linq query.

Related

How to call a local method from the linq query

In my web api i need to execute a method from linq query itself. My linq query code snippet belongs to method is shown below which calls local method to get required data.
var onlineData = (from od in db.RTLS_ONLINEPERSONSTATUS
let zoneIds = db.RTLS_PERSONSTATUS_HISTORY.Where(p => p.person_id == od.PERSONID).OrderByDescending(z => z.stime > startOfThisDay && z.stime < DateTime.Now).Select(z => z.zone_id).ToList()
let zoneIdsArray = this.getZoneList((zoneIds.ToArray()))
let fzones = zoneIdsArray.Select(z => z).Take(5)
select new OnlineDataInfoDTO
{
P_ID = od.PERSONID,
T_ID = (int)od.TAGID,
LOCS = fzones.ToList()
}
public int[] getZoneList(decimal[] zoneIdsArray)
{
int[] zoneIds = Array.ConvertAll(zoneIdsArray, x => (int)x);
List<int> list = zoneIds.ToList();
for (int c = 1; c < zoneIdsArray.Count(); c++)
{
if (zoneIdsArray[c] == zoneIdsArray[c - 1])
{
list.Remove((int)zoneIdsArray[c]);
}
}
return list.ToArray();
}
I am getting exception at let zoneIdsArray = this.getZoneList((zoneIds.ToArray())), is there any way to solve this problem. I got logic to solve my problem from this link(Linq query to get person visited zones of current day ), the given logic is absolutely fine for my requirement but i am facing problem while executing it.
One way to achieve that would be to perform the projection on the client instead of the underlying LINQ provider. This can be done by separating your query into 2 steps:
var peopleStatus =
from od in db.RTLS_ONLINEPERSONSTATUS
let zoneIds = db.RTLS_PERSONSTATUS_HISTORY
.Where(p => p.person_id == od.PERSONID)
.OrderByDescending(z => z.stime > startOfThisDay && z.stime < DateTime.Now)
.Select(z => z.zone_id)
.ToList()
select new
{
Person = od,
ZoneIds = zoneIds,
};
var onlineData =
from od in peopleStatus.ToList()
let zoneIdsArray = this.getZoneList((od.ZoneIds.ToArray()))
let fzones = zoneIdsArray.Select(z => z).Take(5)
select new OnlineDataInfoDTO
{
P_ID = od.Person.PERSONID,
T_ID = (int)od.Person.TAGID,
LOCS = fzones.ToList()
};

Linq Subquery in IQueryable Select

I am having problems with subqueries in a linq-to-entities IQueryable query.
Can anybody tell me what is the correct way to do a sub query when building up an IQueryable query? Based on my full example below.
I get the following error when ToArray() is called on the query:
An exception of type 'System.NotSupportedException' occurred in System.Data.Entity.dll but was not handled in user code
Additional information: LINQ to Entities does not recognize the method 'System.Data.Entity.IDbSet`1[MyDomain.NewsWorthyPressReleases.NewsWorthyWire] Set[NewsWorthyWire]()' method,
and this method cannot be translated into a store expression.
So for example you can see one of my subqueries here:
BwIncluded = (from abw in Context.Set<NewsWorthyWire>()
where abw.WireId == PressWireIds.BUID
where abw.NewsWorthyCampaignId == nc.Id
select abw).Any(),
I am trying to populate BwIncluded with true or false if any() exists.
And the entire build up of the query is as follows, it is IMPORTANT to understand where the sub-queries are used:
private Func<EntityFramework.IDbContext, IQueryable<NewsWorthyPressRelease>> GetSearchNewsWorthyQuery(NewsWorthySearchFields searchFields)
{
return context =>
{
//domain models
var newsWorthyCampaigns = context.Set<NewsWorthyCampaign>();
var wires = context.Set<NewsWorthyWire>();
var campaigns = context.Set<Campaign>();
//predicates
var newsWorthyCampaignPredicate = PredicateBuilder.True<NewsWorthyCampaign>();
var wirePredicate = PredicateBuilder.True<NewsWorthyWire>();
var campaignPredicate = PredicateBuilder.True<Campaign>();
// build up the predicate queries
//Status was input
if (searchFields.StatusId.HasValue && searchFields.StatusId.Value > 0)
{
newsWorthyCampaignPredicate = newsWorthyCampaignPredicate.And(x => x.Id == searchFields.StatusId);
}
//Id was input
if (searchFields.Id.HasValue && searchFields.Id.Value > 0)
{
wirePredicate = wirePredicate.And(x => x.Id == searchFields.Id);
}
//Title was input
if (!string.IsNullOrEmpty(searchFields.Title))
{
wirePredicate = wirePredicate.And(x => x.Title.Contains(searchFields.Title));
}
//Wire was input
if (searchFields.PressWireId.HasValue && searchFields.PressWireId.Value > 0)
{
wirePredicate = wirePredicate.And(x => x.Id == searchFields.PressWireId);
}
//Created By was chosen
if (searchFields.CreatedById.HasValue && searchFields.CreatedById.Value > 0)
{
campaignPredicate = campaignPredicate.And(x => x.IdentityId == searchFields.CreatedById);
}
//Create Date From was chosen
if (searchFields.DateCreatedFrom.HasValue)
{
campaignPredicate = campaignPredicate.And(y => y.CreationDate >= searchFields.DateCreatedFrom);
}
//Create Date To was chosen
if (searchFields.DateCreatedTo.HasValue)
{
campaignPredicate = campaignPredicate.And(y => y.CreationDate <= searchFields.DateCreatedTo);
}
//the query
var nwprQuery = (from nc in newsWorthyCampaigns.Where(newsWorthyCampaignPredicate)
join w in wires.Where(wirePredicate)
on nc.Id equals w.NewsWorthyCampaignId
join c in campaigns.Where(campaignPredicate)
on nc.CampaignId equals c.Id
select new NewsWorthyPressRelease
{
Id = nc.Id,
Title = w.Title,
//BwIncluded = false,
//GnIncluded = false,
//PrIncluded = false,
BwIncluded = (from abw in Context.Set<NewsWorthyWire>()
where abw.WireId == PressWireIds.BUID
where abw.NewsWorthyCampaignId == nc.Id
select abw).Any(),
GnIncluded = (from agw in Context.Set<NewsWorthyWire>()
where agw.WireId == PressWireIds.GLID
where agw.NewsWorthyCampaignId == nc.Id
select agw).Any(),
PrIncluded = (from anw in Context.Set<NewsWorthyWire>()
where anw.WireId == PressWireIds.PRID
where anw.NewsWorthyCampaignId == nc.Id
select anw).Any(),
CreatedBy = c.CreatedBy.FirstName + " " + c.CreatedBy.Surname,
CreateDate = c.CreationDate,
Status = nc.NewsWorthyStatus.Name,
}).AsNoTracking();
return nwprQuery;
};
}
Can anyone help with this?
Thanks

pagination in C# console application [duplicate]

var q = (from Comments in db.tblBlogComments where Comments.blogID == this.ID orderby Comments.date descending select new {
Comments.userID, Comments.comment, Comments.date
});
This returns ALL my associated records, how best would I select say records #10 to #20 only so I don't load any redundant data?
How about:
var q = (
from Comments in db.tblBlogComments
where Comments.blogID == this.ID
orderby Comments.date descending
select new { Comments.userID, Comments.comment, Comments.date }).Skip(10).Take(10);
You can use the .Skip() and .Take() methods on your result set. Example:
var q = (from Comments in db.tblBlogComments where Comments.blogID == this.ID orderby Comments.date descending select new {
Comments.userID, Comments.comment, Comments.date
});
And then use:
int pageSize = 10;
int page = 3;
var currentPage = q.Skip((currentPage - 1) * pageSize).Take(pageSize);
And then
foreach(var item in currentPage)
{
...
}
Since Linq uses deferred execution, the actual query will be created and executed during the foreach loop. So the SQL query will only return the records for the current page.
Edit: More information about this subject
int start = 10;
int end = 20;
var q = (from Comments in db.tblBlogComments
where Comments.blogID == this.ID
orderby Comments.date descending
select new {
Comments.userID,
Comments.comment,
Comments.date
}).Skip(start).Take(end - start);
I'm not sure if Skip translates to SQL executed in the database, so this might be not so efficient.

LINQ to Entities does not recognize the method

This is my Code where I am fetching data.
var list = (from u in _dbContext.Users
where u.IsActive
&& u.IsVisible
&& u.IsPuller.HasValue
&& u.IsPuller.Value
select new PartsPullerUsers
{
AvatarCroppedAbsolutePath = u.AvatarCroppedAbsolutePath,
Bio = u.Bio,
CreateDateTime = u.CreationDate,
Id = u.Id,
ModifieDateTime = u.LastModificationDate,
ReviewCount = u.ReviewsReceived.Count(review => review.IsActive && review.IsVisible),
UserName = u.UserName,
Locations = (from ul in _dbContext.UserLocationRelationships
join l in _dbContext.Locations on ul.LocationId equals l.Id
where ul.IsActive && ul.UserId == u.Id
select new PartsPullerLocation
{
LocationId = ul.LocationId,
Name = ul.Location.Name
}),
Rating = u.GetPullerRating()
});
Now Here is my Extension.
public static int GetPullerRating(this User source)
{
var reviewCount = source.ReviewsReceived.Count(r => r.IsActive && r.IsVisible);
if (reviewCount == 0)
return 0;
var totalSum = source.ReviewsReceived.Where(r => r.IsActive && r.IsVisible).Sum(r => r.Rating);
var averageRating = totalSum / reviewCount;
return averageRating;
}
I have check this Post LINQ to Entities does not recognize the method
And I come to know I need to use
public System.Linq.Expressions.Expression<Func<Row52.Data.Entities.User, int>> GetPullerRatingtest
But how ?
Thanks
You can use conditionals inside LINQ to Entity queries:
AverageRating = u.ReviewsReceived.Count(r => r.IsActive && r.IsVisible) > 0 ?
u.ReviewsReceived.Where(r => r.IsActive && r.IsVisible).Sum(r => r.Rating) /
u.ReviewsReceived.Count(r => r.IsActive && r.IsVisible)
: 0
This will be calculated by the server, and returned as part of your list. Although with 10 million rows like you said, I would do some serious filtering before executing this.
Code within LINQ (to Entities) query is executed within database, so you can't put random C# code there. So you should either use user.GetPullerRating() after it is retrieved or create a property if you don't want to do the calculation every time.
You can also do:
foreach (var u in list)
u.Rating = u.GetPullerRating()
By the way, why is it extension method.

linq if statement, or stored procedure if statements

I am looking to run a piece of code in the database. However there is no supported translation to sql (using linq to sql).
How to convert this code logic ro either inline in linq or in a stored procedure? I have no knowledge of db and stored procedures so preferably I would like to write it in linq.
public Post GetPageOwner(int pageid)
{
var posts = (from dp in db.Posts where dp.pageid == pageid select dp);
var returned = posts;
if (posts.Count() > 0)
{
var latest = posts.OrderByDescending(o => o.Date).FirstOrDefault();
var sharedsamedayaslatest = (from p in posts where p.Date.AddDays(1) >= latest.Date select p);
if (sharedsamedayaslatest.Count() > 1)
{
var followedpost = (from p in posts from s in db.Subscriptions where s.Subscriber == UID && s.Subscribedto == p.UserId select p);
var count = followedpost.Count();
if (count == 1)
{
returned = followedpost;
}
else if (count > 1)
{
returned = (from s in followedpost let reposts = GetPostReposts(s.id) let rating = GetPostRating(s.id) let score = reposts + rating orderby score descending select s);
}
else
{
//no follower shared this post so return the most liked
returned = (from s in sharedsamedayaslatest let reposts = GetPostReposts(s.id) let rating = GetPostRating(s.id) let score = reposts + rating orderby score descending select s);
}
}
else
{
//no shares on the day the latest share
returned = sharedsamedayaslatest;
}
}
else
{
//only one post
returned = posts;
}
return returned.FirstOrDefault(); //order by userid gets a random one
}
May be something like this would work:
public Post GetPageOwner(int pageid)
{
var posts = (from dp in db.Posts where dp.pageid == pageid select dp);
var returned = posts;
if (posts.Count() > 0)
{
var latest = posts.OrderByDescending(o => o.Date).FirstOrDefault();
var sharedsamedayaslatest = (posts.Where(p => p.Date.AddDays(1) >= latest.Date));
if (sharedsamedayaslatest.Count() > 1)
{
var followedpost = (posts.SelectMany(p => db.Subscriptions, (p, s) => new {p, s}).Where(
#t => s.Subscriber == UID && s.Subscribedto == p.UserId).Select(#t => p));
var count = followedpost.Count();
if (count == 1)
{
returned = followedpost;
}
else if (count > 1)
{
returned = (followedpost.Select(s => new {s, reposts = GetPostReposts(s.id)}).Select(
#t => new {#t, rating = GetPostRating(s.id)}).Select(
#t => new {#t, score = reposts + rating}).OrderByDescending(#t => score).Select(#t => s));
}
else
{
//no follower shared this post so return the most liked
(sharedsamedayaslatest.Select(s => new {s, reposts = GetPostReposts(s.id)}).Select(
#t => new {#t, rating = GetPostRating(s.id)}).Select(
#t => new {#t, score = reposts + rating}).OrderByDescending(#t => score).Select(#t => s)) = returned;
}
}
else
{
//no shares on the day the latest share
returned = sharedsamedayaslatest;
}
}
else
{
//only one post
returned = posts;
}
return returned.FirstOrDefault(); //order by userid gets a random one
}

Categories

Resources