Html Decode with Lambda Expression in .Net - c#

I am trying to decode HTML in lambda expression but its giving following error:
"LINQ to Entities does not recognize the method 'System.String HtmlDecode(System.String)' method, and this method cannot be translated into a store expression."
And I am using code as bellow:
OtherUserInformation userData = db.Users
.Where(u => u.UserID.Equals(inputUserid))
.Select(x => new OtherUserInformation
{
Address = x.location == null ? "" : x.location,
UserPic = db.UserProfile
.Where(u => u.UserID.Equals(x.UserID))
.Select(y => y.profileImg)
.FirstOrDefault() == null
? profileImagePath + "140_profile_default.jpg"
: profileImagePath + "140_" + db.UserProfile
.Where(u => u.UserID.Equals(x.UserID))
.Select(y => y.profileImg)
.FirstOrDefault(),
CoverPic = db.UserProfile
.Where(u => u.UserID.Equals(x.UserID))
.Select(y => y.CoverImg)
.FirstOrDefault() == null
? coverImagePath + "812_cover_default.jpg"
: coverImagePath + coverPicPrefix + db.UserProfile
.Where(u => u.UserID.Equals(x.UserID))
.Select(y => y.CoverImg)
.FirstOrDefault(),
Detail = db.UserProfile
.Where(u => u.UserID.Equals(x.UserID))
.Select(y => y.About).FirstOrDefault() == null
? ""
: WebUtility.HtmlDecode(db.UserProfile
.Where(u => u.UserID.Equals(x.UserID))
.AsEnumerable()
.Select(y => y.About)
.FirstOrDefault()),
FollowerCount = db.FollowUser
.Where(u => u.FriendId.Equals(x.UserID) && u.FollowStatus.Equals(1))
.Count(),
Name = x.FirstName + " " + x.LastName,
IsFollow = db.FollowUser
.Where(u => u.UserId.Equals(userAuthInfo.UserId)
&& u.FriendId.Equals(inputUserid)
&& u.FollowStatus.Equals(1))
.Select(z => z)
.FirstOrDefault() == null ? "False" : "True",
})
.FirstOrDefault();
In above code, I need "Detail" field which have HTML encoded data. But I am not able to decode html in lambda expression.
Any help would be highly appreciate.

You can't use that method, or any like it, before you have resolved your query because sql doesn't know anything about that assembly. If it's not an EntityFunction then you have to reproject the list after resolution. If you use a data mapper like AutoMapper you can just use that in the reprojection and make the call there but if you need to do it by hand do it after you call toList().
db.Users.Select(x=>new YourObject{//data})
.ToList()
.Select(x=>new YourObject{
//now you can use whatever methods you want from whatever assemblies you want
SomePropertyValue = x.SomePropertyValue,
SomeOtherValue = SomeAssembly.SomeMethod(x.SomeOtherValue)
});

I got solution for this and added few line of code at the bottom of above query as bellow:
}).FirstOrDefault().AsEnumerable().Select(x => new OtherUserInformation
{
Address = x.Address,
UserPic = x.UserPic,
CoverPic = x.CoverPic,
Detail = Regex.Replace(x.Detail, "<.*?>", string.Empty),
FollowerCount = x.FollowerCount,
Name = x.Name,
IsFollow = x.IsFollow,
Categories = x.Categories,
Followers = x.Followers
}).FirstOrDefault();
Above solution worked for me. Happy coding :)

Try the HttpUtility.HtmlDecode Method instead
http://msdn.microsoft.com/en-us/library/system.web.httputility.htmldecode(v=vs.110).aspx
Or try the decoding the field inside the Select method as per the example below:
OtherUserInformation userData = db.Users.Where(u => u.UserID.Equals(inputUserid)).Select(x => new OtherUserInformation
{
Address = x.location == null ? "" : x.location,
// UserPic = Utilities.ImagePathForProfileForUserByDiviceType(db.UserProfile.Where(u => u.UserID.Equals(x.UserID)).Select(y => y.profileImg).FirstOrDefault(),deviceType),
// CoverPic = Utilities.ImagePathForCoverImageForUserByDiviceType(db.UserProfile.Where(u => u.UserID.Equals(x.UserID)).Select(y => y.CoverImg).FirstOrDefault(), deviceType),
UserPic = db.UserProfile.Where(u => u.UserID.Equals(x.UserID)).Select(y => y.profileImg).FirstOrDefault() == null ? profileImagePath + "140_profile_default.jpg" : profileImagePath + "140_" + db.UserProfile.Where(u => u.UserID.Equals(x.UserID)).Select(y => y.profileImg).FirstOrDefault(),
CoverPic = db.UserProfile.Where(u => u.UserID.Equals(x.UserID)).Select(y => y.CoverImg).FirstOrDefault() == null ? coverImagePath + "812_cover_default.jpg" : coverImagePath + coverPicPrefix + db.UserProfile.Where(u => u.UserID.Equals(x.UserID)).Select(y => y.CoverImg).FirstOrDefault(),
Detail = db.UserProfile.Where(u => u.UserID.Equals(x.UserID)).Select(y => y.About).FirstOrDefault() == null ? "" : db.UserProfile.Where(u => u.UserID.Equals(x.UserID)).AsEnumerable().Select(y => WebUtility.HtmlDecode(y.About)).FirstOrDefault(),
FollowerCount = db.FollowUser.Where(u => u.FriendId.Equals(x.UserID) && u.FollowStatus.Equals(1)).Count(),
Name = x.FirstName + " " + x.LastName,
IsFollow = db.FollowUser.Where(u => u.UserId.Equals(userAuthInfo.UserId) && u.FriendId.Equals(inputUserid) && u.FollowStatus.Equals(1)).Select(z => z).FirstOrDefault() == null ? "False" : "True",
})
}).FirstOrDefault();

Related

How to iterate over a list to build a Linq query

I have the following working query:
posts.Where(post =>
post.Fields
.Where(x =>
x.RegionId == "RecipeArticleDetails" &&
(x.FieldId == "RecipePrepTime" || x.FieldId == "RecipeCookTime")
)
.GroupBy(x => x.PostId)
.Select(x => new { ID = x.Key, Value = x.Sum(y => Convert.ToInt32(y.Value)) })
.Where(x => x.Value > 10 && x.Value < 40)
.Any()
)
List<string> suppliedTimes = new List<string>(){
"10-60","0-10"
};
I would like to replace Where(x => x.Value > 10 && x.Value < 40) so it looks up from a list of ranges:
List<string> suppliedTimes = new List<string>(){
"10-60","0-10"
};
My understanding is I can use select to iterate over the items:
posts.Where(post =>
suppliedTimes.Select(x => new {low = Convert.ToInt32(x.Split("-",StringSplitOptions.RemoveEmptyEntries)[0]), high = Convert.ToInt32(x.Split("-",StringSplitOptions.RemoveEmptyEntries)[1]) })
.Any( a =>
post.Fields
.Where(x =>
x.RegionId == "RecipeArticleDetails" &&
(x.FieldId == "RecipePrepTime" || x.FieldId == "RecipeCookTime")
)
.GroupBy(x => x.PostId)
.Select(x => new { ID = x.Key, Value = x.Sum(y => Convert.ToInt32(y.Value)) })
.Where(x => x.Value > a.low && x.Value < a.high)
.Any()
)
)
However this code results in the error:
could not be translated. Either rewrite the query in a form that can be translated, or switch to client evaluation explicitly by inserting a call to 'AsEnumerable', 'AsAsyncEnumerable', 'ToList', or 'ToListAsync'. See https://go.microsoft.com/fwlink/?linkid=2101038 for more information.
Please can someone explain how I can achieve this and why what I have isn't working.
To make it work with EF Core I would suggest my extnsion FilterByItems and change the way how to retrieve records.
List<string> suppliedTimes = new List<string>(){
"10-60","0-10"
};
var ranges = suppliedTimes
.Select(x => x.Split("-", StringSplitOptions.RemoveEmptyEntries))
.Select(x => new {
low = Convert.ToInt32(x[0]),
high = Convert.ToInt32(x[1])
});
var fields = context.Fields
.Where(x =>
x.RegionId == "RecipeArticleDetails" &&
(x.FieldId == "RecipePrepTime" || x.FieldId == "RecipeCookTime")
)
.GroupBy(x => x.PostId)
.Select(x => new { ID = x.Key, Value = x.Sum(y => Convert.ToInt32(y.Value)) })
.FilterByItems(ranges, (e, r) => e.Value > r.low && e.Value < r.high, true);
var posts = posts
.Join(fields, p => p.Id, f => f.ID, (p, f) => p);

Is there a way to set this entity/linq query to IEnumerable?

I'm trying to return an IEnumerable activities instead of "var"
var activities = ctx.Activities.Where(a => a.SiteID == propID)
.Where(a => a.ActivityTypeName == "Call")
.Select(x => new
{
x.DateTimeEntry,
x.Contact.OwnerContact.ParcelDatas
.FirstOrDefault(a => a.OwnerContactID == x.Contact.OwnerContact.OOwnerID)
.Parcel_LetterTracking.LMailDate,
x.FAQs.FirstOrDefault(a => a.ActivityID == x.ActivityID)
.FAQ_Library.FaqNum,
x.FAQs.FirstOrDefault(a => a.ActivityID == x.ActivityID)
.FAQ_Library.Question
});
edit: data type Object compiles but I'm not sure if that's right.
.Select already returns a an IEnumerable<TResult> also combine your ..where() clauses with && instead. https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.select?view=netframework-4.8 also one other thing you can do is use .AsEnuemerable()
var activities = ctx.Activities.Where(a => a.SiteID == propID && a.ActivityTypeName == "Call")
.Select(x => new
{
x.DateTimeEntry,
x.Contact.OwnerContact.ParcelDatas.FirstOrDefault(a => a.OwnerContactID == x.Contact.OwnerContact.OOwnerID).Parcel_LetterTracking.LMailDate,
x.FAQs.FirstOrDefault(a => a.ActivityID == x.ActivityID).FAQ_Library.FaqNum,
x.FAQs.FirstOrDefault(a => a.ActivityID == x.ActivityID).FAQ_Library.Question
}).AsEnumerable();

Two dbcontexts cause an error "value cannot be null. parameter name entitytype"

I have 2 DbContexts in my application, and need to do a join in 2 tables that are each one in a different DbContext; I get this error
value cannot be null. parameter name entitytype
When I try to join 2 tables of the same context, this error does not happen.
var VerificaExistenciaSinistro = sinistroContext.SnsAviso
.Join(
sinistroContext.SnsNumAviso,
sinistro => sinistro.NumApo,
aviso => aviso.NumApo,
(sinistro, aviso) => new {
sinistroV = sinistro,
avisoV = aviso })
.Where(c => c.sinistroV.CodItm == c.avisoV.CodItm &&
c.sinistroV.NumApo == c.avisoV.NumApo &&
c.sinistroV.NumAvs == c.avisoV.SeqNumAvs)
.Join(sgsContext.EmsEmissao,
sinistro1 => sinistro1.sinistroV.CodCtrtAvs,
emissao => emissao.CodCtrt,
(sinistro1, emissao) => new {
sinistroC = sinistro1,
emissaoC = emissao })
.Where(c => c.sinistroC.sinistroV.CodCtrtAvs == c.emissaoC.CodCtrt &&
c.emissaoC.CodEmis == c.sinistroC.avisoV.CodEms)
.Where(x => x.sinistroC.sinistroV.NumApo == apolice &&
x.emissaoC.StsEmis == emissao &&
x.emissaoC.NumEndosso ==endosso &&
x.sinistroC.sinistroV.CodItm == cod_itm &&
x.sinistroC.sinistroV.CodCbe == cbeCod)
.Select(x => x.sinistroC)
.ToList();
It generally occurs when u query data from two dbcontext using IQueryable
I encountered the same issue when I was using two dbContext. The solution which I found was. If u are using join between two tables then load any one table's data first to a variable/Object so that It becomes IEnumerable or IList and then do join with that variable/Object to the another table of another dbContext
Example
var FirstDbContextTable = sinistroContext.SnsAviso
.Join(
sinistroContext.SnsNumAviso,
sinistro => sinistro.NumApo,
aviso => aviso.NumApo,
(sinistro, aviso) => new {
sinistroV = sinistro,
avisoV = aviso })
.Where(c => c.sinistroV.CodItm == c.avisoV.CodItm &&
c.sinistroV.NumApo == c.avisoV.NumApo &&
c.sinistroV.NumAvs == c.avisoV.SeqNumAvs).ToList();
var result=FirstDbContextTable.Join(sgsContext.EmsEmissao,
sinistro1 => sinistro1.sinistroV.CodCtrtAvs,
emissao => emissao.CodCtrt,
(sinistro1, emissao) => new {
sinistroC = sinistro1,
emissaoC = emissao })
.Where(c => c.sinistroC.sinistroV.CodCtrtAvs == c.emissaoC.CodCtrt &&
c.emissaoC.CodEmis == c.sinistroC.avisoV.CodEms)
.Where(x => x.sinistroC.sinistroV.NumApo == apolice &&
x.emissaoC.StsEmis == emissao &&
x.emissaoC.NumEndosso ==endosso &&
x.sinistroC.sinistroV.CodItm == cod_itm &&
x.sinistroC.sinistroV.CodCbe == cbeCod)
.Select(x => x.sinistroC)
.ToList();

Can this LINQ be more efficient?

I have a fairly complex linq grouping with some repetition that annoys me, but I haven't been able to reduce it. Is there any way to avoid getting the list of items with ID=="XYZ" twice?
var example = = new GdsObservableCollection<GroupedQueryResults>(
items.Where(a => a.SubCategory3 != "{template}")
.GroupBy(item => item.SubCategory1)
.Select(g => new GroupedQueryResults
{
SubCategory = g.Key,
SectionHeader = (g.Count(x => x.Id == "XYZ") > 0) ?
"Category :" + g.Where(x => x.Id == "XYZ")
.First().NewValue :
"Item - " + itemNumber
...
The duplicate search for x.Id == "XYZ" can be avoided by using Where + Select + FirstOrDefault chain combined with C# null-coalescing operator:
SectionHeader = g
.Where(x => x.Id == "XYZ")
.Select(x => "Category :" + x.NewValue)
.FirstOrDefault() ?? "Item - " + itemNumber
I wouldn't say more efficient, but can be a little bit smaller, as you can use predicates inside Any and First:
var example = new GdsObservableCollection<GroupedQueryResults>(
items.Where(a => a.SubCategory3 != "{template}")
.GroupBy(item => item.SubCategory1)
.Select(g => new GroupedQueryResults
{
SubCategory = g.Key,
SectionHeader = g.Any(x => x.Id == "XYZ") ?
"Category :" + g.First(x => x.Id == "XYZ").NewValue :
"Item - " + itemNumber

LINQ left self join

I have LINQ query as below:
lst_direct_managers = context.sf_guard_user_profile
.Join(context.sf_guard_user_profile, up => up.user_id, dm => dm.direct_manager_id,
(up, dm) => new { up, dm })
.Where(m => m.up.is_gvo == 1)
.Select(m => new DirectManagerModel
{
user_id = m.up.direct_manager_id == null ? 0 : m.up.direct_manager_id,
dm_full_name = (m.up.first_name + " " + m.up.last_name == null ? "No Direct Manager" : m.up.first_name + " " + m.up.last_name)
})
.Distinct()
.OrderBy(m => m.dm_full_name).ToList();
Problem is that it does not return default value in case of nulls "No Direct Manager". Can you please help me?

Categories