LINQ throws error on using Regex.Split() - c#

ERROR
LINQ to Entities does not recognize the method 'System.String[] Split(System.String, System.String)' method, and this method cannot be translated into a store expression.
FOR CODE
var getfrmbid = (from e in _dbEntity.FormNames
where e.form_id == id & e.type == "Form"
select new FormsCreationModel
{
form_name = e.form_name,
form_id = e.form_id,
formfields = (from i in _dbEntity.FormDetails
where e.form_id == i.form_id
select i).AsEnumerable().Select(x=> new FormDetailsModel()
{
field_default = x.field_default,
field_id = x.field_id,
field_mandatory = x.field_mandatory,
field_maxlength = x.field_maxlength,
field_name = x.field_name,
field_type = x.field_type,
field_validation = x.field_validation,
field_value = Regex.Split(x.field_value, " ^ ").Select(item => new DropDownValue() { DDValue = item }).ToList()
}).ToList()
}).Single();
NOTE
Error Spot at field_value is of type List<DropDownValue> in FormDetailsModel
x.field_value is a String and I am converting it into an String[] using Regex.Split() and then to List<DropDownValue> to assign it on field_value.
How could I assign field_value from x.field_value after splitting?

You must replace
select i).AsEnumerable().Select(x=> new FormDetailsModel()
with
select i).ToList().Select(x=> new FormDetailsModel()
When you use .ToList(), DB is queried and Select extension runs locally. Otherwise lambda expression is compiled into sql query and clearly SQL doesn't know Regex.Split(). In Linq2Objects you can use that methods since it runs locally. It's important have in mind what LinqTo* you are using.

Related

Linq: let Count result into a specified column

I've got a table Installation which can contains one or many Equipements.
And for functionnal reasons, I've overwritten my table Installation and added a field NbrEquipements.
I want to fill this field with Linq, but I'm stuck...
Due to special reasons, there is no relation between these to tables. So, no Installation.Equipements member into my class. Therefore, no Installation.Equipements.Count...
I'm trying some stuff. Here is my code:
var query = RepoInstallation.AsQueryable();
// Some filter
query = query.Where(i => i.City.RegionId == pRegionId));
int?[] etatIds = { 2, 3 };
query = (from i in query
select new Installation
{
NbrEquipements= (from e in RepoEquipement.AsQueryable()
where e.InstallationSpecialId == i.SpecialId
&& (etatIds.Contains(e.EquEtat))
select e.SasId
).Count()
});
But with this try, I got this error:
The entity or complex type 'myModel.Installation' cannot be constructed in a LINQ to Entities query
I've tried some other stuff but I'm always turning around...
Another thing that can be useful for me: It would be great to fill a field called Equipements which is a List<Equipement>.
After that, I would be able to Count this list...
Is it possible ?
Tell me if I'm not clear.
Thanks in advance.
Here is the final code:
//In the class:
[Dependency]
public MyEntities MyEntities { get; set; }
//My Methode code:
var query = MyEntities .SasInstallations.AsQueryable();
// Some filter
query = query.Where(i => i.City.RegionId == pRegionId));
var liste = new List<Installation>();
var queryWithListEquipements =
from i in query
select new
{
Ins = i,
EquipementsTemp = (from eq in MyEntities.Equipements.AsQueryable()
where eq.SpecialId == i.SpecialId
&& (etatIds.Contains(eq.SasEquEtat))
select eq
).ToList()
};
var listWithListEquipements = queryWithListEquipements.ToList();
foreach (var anonymousItem in listWithListEquipements)
{
var ins = anonymousItem.Ins;
ins.Equipements = anonymousItem.EquipementsTemp;
ins.NumberEquipements = ins.Equipements.Count();
liste.Add(ins);
}
return liste;
By the way, this is very very fast (even the listing of Equipements). So this is working exactly has I wished. Thanks again for your help everyone!
Use an anonymous type. EF does not like to instantiate entity classes inside a query.
var results = (from i in query
select new
{
NbrEquipements= (from e in RepoEquipement
where e.InstallationSpecialId == i.SpecialId
&& (etatIds.Contains(e.EquEtat))
select e.SasId
).Count()
})
.ToList();
Notice how I used select new instead of select new Installation.
You can then use the data inside the list (which is now in memory) to create instances of type Installation if you want like this:
var installations = results.Select(x =>
new Installation
{
NbrEquipements = x.NbrEquipements
}).ToList();
Here is how to obtain the list of equipment for each installation entity:
var results = (from i in query
select new
{
Installation = i,
Equipment = (from e in RepoEquipement
where e.InstallationSpecialId == i.SpecialId
&& (etatIds.Contains(e.EquEtat))
select e).ToList()
})
.ToList();
This will return a list of anonymous objects. Each object will contain a property called Installation and another property called Equipment (which is a list). You can easily convert this list (of anonymous objects) to another list of whatever type that you want.

Linq except two IEnumerable queries

I have a two linq query that returns type of IEnumerable. First query returns filtered values and second query return all values I want to except from second query to first query like minus operator in SQL and bind to my listboxs.
my code sample =>
using (ISession session = SessionManager.CurrentSession)
{
IEnumerable<RoleDefinition> roleAssigned = from groupRole in session.Query<GroupRole>()
join roleDef in session.Query<RoleDefinition>() on groupRole.RoleDefinitionId equals
roleDef.RoleDefinitionId
where groupRole.GroupId == SelectedGroupId
orderby roleDef.RoleName
select new RoleDefinition
{
RoleName = roleDef.RoleName
};
IEnumerable<RoleDefinition> roleUnassigned = from grole in session.Query<RoleDefinition>()
orderby grole.RoleName
select new RoleDefinition
{
RoleName = grole.RoleName
};
List<RoleDefinition> lRoleAss = roleAssigned.ToList();
List<RoleDefinition> lRoleUnAss = roleUnassigned.ToList();
lRoleUnAss = lRoleUnAss.Where(x => !lRoleAss.Contains(x)).ToList();
lsbAssigned.DataSource = lRoleAss;
lsbAssigned.TextField = "RoleName";
lsbAssigned.ValueField = "RoleName";
lsbAssigned.DataBind();
lsbUnAssigned.DataSource = lRoleUnAss;
lsbUnAssigned.TextField = "RoleName";
lsbUnAssigned.ValueField = "RoleName";
lsbUnAssigned.DataBind();
}
EDIT => I fixed my code as below and my function works successfully
List<RoleDefiniton> filteredUnassign = lRoleUnAss.Where(def => !lRoleAss.Select(x => x.RoleName).Contains(def.RoleName)).ToList();
Change the following line:
lRoleUnAss = lRoleUnAss.Where(x => !lRoleAss.Contains(x)).ToList();
To
var results = lRoleUnAss.Except(lRoleAss).ToList();
and use results to get the final list.
I declared a new variable because i do not know if you want to keep the initial list intact or not. If you do not mind changing it you may try:
lRoleUnAss = lRoleUnAss.Except(lRoleAss).ToList();

Dynamic where clause in LINQ?

I am trying to load data based on Dynamic where condition.
string tempQry = string.Empty;
if (!string.IsNullOrEmpty(cusid) && !string.IsNullOrEmpty(mktid))
tempQry = "x=>x.MarketID==" + mktid + "&& x.MasterCustomerID==" + cusid;
if (string.IsNullOrEmpty(cusid))
tempQry = "x=>x.MarketID==" + mktid;
if (string.IsNullOrEmpty(mktid))
tempQry = "x=>x.MasterCustomerID==" + cusid;
_lstOptInInterest = new LinkedList<OptInInterestArea>(
(from a in _lstOptInInterest
join b in _marketoEntities.CustCommPreferences.Where(tempQry)
on new { CODE = a.Code, SUBCODE = a.SubCode } equals new { CODE = b.Option_Short_Name, SUBCODE = b.Option_Short_Subname }
into leftGroup
from b in leftGroup.DefaultIfEmpty()
select new OptInInterestArea()
{
Code = a.Code,
SubCode = a.SubCode,
SubCodeDescription = a.SubCodeDescription,
CodeDescription = a.CodeDescription,
PrevOptIn = b != null && b.OptedIn == true
}).ToList());
It is giving compilation error Where(tempQry).
'System.Data.Entity.DbSet<Market.Data.CustCommPreference>' does not contain a definition for 'Where' and the best extension method overload 'System.Linq.Queryable.Where<TSource>(System.Linq.IQueryable<TSource>, System.Linq.Expressions.Expression<System.Func<TSource,bool>>)' has some invalid arguments
How to handle this?
Where awaits conditions in form of lambdas rather than strings, so you have to refactor your code a little bit (just an idea below):
IQueryable<CustCommPreference> query = _marketoEntities.CustCommPreferences.AsQueryable();
if (!string.IsNullOrEmpty(cusid))
query = query.Where(x => x.MasterCustomerID == cusid);
if (!string.IsNullOrEmpty(mktid))
query = query.Where(x => x.MarketID == mktid);
and later use it:
...
join b in query
...
see this blog by Scott. It should help you sort your issue
The error you are seeing appears to indicate that you are using EF not LINQ to SQL. Please correct your tags if that is the case. If you want to use strings, consider using ObjectQuery's Where method instead of using DBSet. Alternatively, you could build the entire query using EntitySQL.

EF Select inside Select

I have the following EF Expression:
var complexes = db.ResidentialComplexes.AsNoTracking()
.Where(rc => rc.MasterEntity == entity)
.Select(rc => new CustomComplexObj()
{
ComplexId = rc.ComplexId,
Name = rc.Name,
Region = rc.Region,
Properties = rc.CurrentProperties.Select(p=> new CustomPropertyObj(){
Name = p.Name,
PropertyId = p.PropertyId
}).ToList()
}).ToList();
Im getting an error when setting:
Properties = rc.CurrentProperties.Select(p=> new CustomPropertyObj(){
Name = p.Name,
PropertyId = p.PropertyId
}).ToList()
This is the error:
LINQ to Entities does not recognize the method 'System.Collections.Generic.List1[CondoTrack.Model.Poco.CustomPropertyObj] ToList[CustomPropertyObj](System.Collections.Generic.IEnumerable1[CondoTrack.Model.Poco.CustomPropertyObj])' method, and this method cannot be translated into a store expression.
Any clue on how to get the desired result?
Remove the ToList() and change the Properties type to IEnumerable<T> instead of List<T>. As it is stated in the error, ToList is not supported by Linq to Entities.

Converting t-sql query into EF's method syntax

What would be an EF method syntax equivalent for the following TSQL query?
select istb.service_id, ss.service_desc, selected=1
from istb_services istb
inner join setup_services ss on istb.service_id=ss.service_id
where istb.istb_id=3
union
select ss.service_id, ss.service_desc, selected=0
from setup_services ss
where ss.service_id not in (select service_id from istb_services where istb_id=3)
I tried converting the not in part of the query like following:
var _existing = context.istb_services.Where(e => e.istb_id == IstbID);
var _others = context.setup_services.Except(_existing);
but it is generating compile-time error:
The best overloaded method match for 'System.Data.Objects.ObjectQuery.Except(System.Data.Objects.ObjectQuery)' has some invalid arguments
I understand I can't pass different type of ObjectQuery to the .Except method but then what would be the alternative code?
Thanks,
Try the following:
var resultA =
from istb in istb_services
join ss in setup_services on istb.service_id equals ss.service_id
where istb.istb_id == 3
select new { istb.service_id, ss.service_desc, selected = true };
var resultB =
from ss in setup_services
where !istb_services.Any(istb =>
istb.service_id == ss.service_id &&
istb.istb_id == 3)
select new { ss.service_id, ss.service_desc, selected = false };
var result = resultA.Union(resultB);
Anonymous type initializers having identical fields should be compiled to the same anonymous type, making the two sequences compatible for the Union operation.

Categories

Resources