LINQ to Entities split string on result - c#

I have a LINQ statement as follows:
var playedBanDataList =
from bannedPlayers in query
select new PlayerBanData
{
Admin = bannedPlayers.Admin,
BannedUntil = bannedPlayers.BannedUntil,
IsPermanentBan = bannedPlayers.IsPermanentBan,
PlayerName = bannedPlayers.PlayerName,
Reason = bannedPlayers.Reason,
IpAddresses = bannedPlayers.IpAddresses.Split(new [] {","}, StringSplitOptions.RemoveEmptyEntries).ToList()
};
return playedBanDataList.ToList();
This fails because split function fails on IpAddresses as LINQ to Entities cannot translate this query to SQL.
This makes sense, but then what's an equivalent way of accomplishing this elegantly? The only way I've thought of is to manually run a loop on the retrieved string then splitting it, but I'd like to get it in one go.

You can use AsEnumerable to make the select occur in memory instead of EF.
var playedBanDataList = query.AsEnumerable()
.Select(bannedPlayers => new PlayerBanData
{
Admin = bannedPlayers.Admin,
BannedUntil = bannedPlayers.BannedUntil,
IsPermanentBan = bannedPlayers.IsPermanentBan,
PlayerName = bannedPlayers.PlayerName,
Reason = bannedPlayers.Reason,
IpAddresses = bannedPlayers.IpAddresses.Split(
new [] {","},
StringSplitOptions.RemoveEmptyEntries).ToList()
});

Related

How can get values using LINQ from multilevel variable

I want to unable to fetch values using LINQ. I am using below code for fetching data.
SearchParameters sp3 = new SearchParameters()
{
Filter = "name eq 'test'",
Top = 5,
QueryType = QueryType.Full,
Select= new List<string>() { "Query" },
};
if (highlights)
{
sp3.HighlightPreTag = "<b>";
sp3.HighlightPostTag = "</b>";
}
DocumentSearchResult suggestResult = _indexClient1.Documents.Search(term,sp3);
List<string> suggestions = (from p in suggestResult
.Results.Select(s => s.Document)
.Select(y => y.Values.ToString())
select p).ToList();
Hierarchy is Document->Result->Query.
I am getting values till Result level but I want to get data till Query Level.
I am not expert in LINQ.
screenshot
output
I think what you are looking for is something like this:
suggestResult.Results.SelectMany(s => s.Document.Select(d => d.Query)).ToList()
It should give you a list of all Query-Objects over all Document Results.
If you want the Query as string you have to get another property of Query in the inner Select or call ToString() on it.

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();

LINQ throws error on using Regex.Split()

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.

SolrNet OR query

I am trying to query records where ParentId = thread OR DataId = Thread. The query keeps timing out on me. Is there something wrong with the query below?
var Test = solr.Query(new SolrQueryByField("ParentId", Thread) ||
(new SolrQueryByField("DataId", Thread)));
I am not an expert in Solr.Net but I have used it for one project. I can only suggest you try couple of things.
First go to your SOLR Admin and try executing the query:
(ParentId:"Thread") OR (DataId:"Thread")
If you get any result back and its not timing out, you can use the same string in Solr.Net like:
string strQuery = "(ParentId:\"Thread\") OR (DataId:\"Thread\")";
// or use * for contains instead of double quotes
var query = new SolrQuery(strQuery);
SortOrder sortOrder = new SortOrder("ParentId");
var solrQueryResult = solr.Query(query, new QueryOptions
{
Rows = 100, //Max Rows returned
Start = 0,
OrderBy = new[] { sortOrder }, //If you want the ordered result
});
var list = solrQueryResult.ToList();//if you want list
You can do this without concatenating strings manually:
ISolrOperations<User> solr = ServiceLocator.Current.GetInstance<ISolrOperations<User>>();
var users = solr.Query(new SolrQuery("age:20") || new SolrQuery("age:30"), options);
More info here:
https://github.com/mausch/SolrNet/blob/master/Documentation/Querying.md

Entity Framework - Join to a List

I need to retrieve a list of entities from my database that matches a list of items in a plain list (not EF). Is this possible with Entity Framework 4.1?
Example:
var list = new List<string> { "abc", "def", "ghi" };
var items = from i in context.Items
where list.Contains(i.Name)
select i;
This works great to return rows that match one property, but I actually have a more complex property:
var list = new List<Tuple<string, string>>
{
new Tuple<string,string>("abc", "123"),
new Tuple<string,string>("def", "456")
};
// i need to write a query something like this:
var items = from i in context.Items
where list.Contains(new Tuple<string,string>(i.Name, i.Type))
select i;
I know that is not valid because it will say it needs to be a primitive type, but is there any way to do what I'm trying to accomplish or will I need to resort to a stored procedure?
You have a few options:
1) You could, of course, write a stored procedure to do what you need and call it.
2) You could read the table into memory and then query the in memory list...that way you don't have to use primitives:
var items = from i in context.Items.ToList()
where list.Contains(new Tuple<string, string>(i.Name, i.Type))
select i;
3) You could also convert your query to use primitives to achieve the same goal:
var items = from i in context.Items
join l in list
on new { i.Name, i.Type } equals
new { Name = l.Item1, Type = l.Item2 }
select i;
I would go with the second option as long as the table isn't extremely large. Otherwise, go with the first.
You need to break it down to sub-properties. For example, something like (this might not compile, i'm not able to test at the moment, but it should give you something to work with):
var items = from i in context.Items
where list.Select(x => x.Item1).Contains(i.Name)
&& list.Select(x => x.Item2).Contains(i.Type)
select i;
You have to think about what the resulting SQL would look like, this would be difficult to do directly in SQL.
My suggestion would be you split out one field of the tuples and use this to cut down the results list, get back the query result then filter again to match one of the tuples e.g.
var list = new List<string> { "abc", "def" };
var list2 = new List<Tuple<string, string>>
{
new Tuple<string,string>("abc", "123"),
new Tuple<string,string>("def", "456")
};
var items = (from i in context.Items
where list.Contains(i.Name)
select i)
.AsEnumerable()
.Where(i => list2.Any(j => j.val1 == i.Name && j.val2 == i.Type);

Categories

Resources