How can l use Regex.Replace method within LINQ - c#

I have a controller with following method getMail():
public JsonResult getMail(string id)
{
int Id = Convert.ToInt32(id);
string pattern = #"\bmem_id\b";
string replace = "100";
var result = (from a in db.tblmail_type
where a.Id == Id
select new MailModel
{
subject = a.Subject,
Content = Regex.Replace(a.Content, pattern, replace);
});
return Json(result, JsonRequestBehavior.AllowGet);
}
This method is used for getting mail content. Before getting content, I want to replace a "mem_id" to "100" in the mail content. Default content is given below:
Content = "You have successfully registered with Member ID: mem_id"
I have used Regex.Replace() method in the LINQ. But this code doesn't change the content. When I change this code to this form which is given below, it's work properly.
public JsonResult getMail(string id)
{
int Id = Convert.ToInt32(id);
var input = db.tblmail_type.Where(x=>x.Id==Id).FirstOrDefault().Content;
string pattern = #"\bmem_id\b";
string replace = "100";
string content = Regex.Replace(input, pattern, replace);
var result = (from a in db.tblmail_type
where a.Id == Id
select new MailModel
{
subject = a.Subject,
Content = content
});
return Json(result, JsonRequestBehavior.AllowGet);
}
Why does this happen? Can anyone specify the reason behind this weird problem? How can I replace the "Content" within the LINQ?

You can use any one of the following solutions,
Solution 1:
Unfortunatelly, you won't be able to send the regex processing logic directly to the database.
You'll need to get the Content from the database and then iterate over the list and apply regex.
This can be done by using AsEnumerable(). It breaks the query into two part.
First part is inside part( query before AsEnumerable()) is executed as Linq-to-SQL.
Second part is outside part( query after AsEnumerable()) is executed as Linq-to-Objects.
First part is executed on database and all data brought in to the client side.
Second part (here it is where, select) is performed on the client side.
So in short AsEnumerable() operator move query processing to client side.
var result = ( from a in db.tblmail_type.AsEnumerable()
where a.Id == Id
select new MailModel {
subject = a.Subject,
Content = Regex.Replace(a.Content, pattern, replace)
});
Solution 2:
var result = db.tblmail_type.Where(x => x.Id == Id).AsEnumerable().Select(x => new MailModel { Content = Regex.Replace(x.Content, pattern, replace) , subject = x.Subject}).ToList();
Solution 3:
var result = db.tblmail_type.Where(x => x.Id == Id).ToList();
result.ForEach(x => x.Content = Regex.Replace(x.Content, pattern, replace));

Related

MVC empty query string parameter strange behaviour

I'm trying to implement search by passing the keyword to controller action as a parameter as shown below:
public ActionResult Index(string query)
{
var contacts = _unitOfWork.Contacts.GetContacts(_user.Id, query);
var viewModel = contacts.Select(Mapper.Map<Contact, ContactViewModel>);
return View("Index", viewModel);
}
GetContacts function in the repository looks like the following:
public IEnumerable<Contact> GetContacts(int userId, string query = null)
{
var list = _context.Contacts
.Where(c => c.UserId == userId)
.OrderBy(c => c.FirstName)
.AsQueryable();
if (query != null)
list = list.Where(c => c.FirstName.ToLower().Contains(query.ToLower())
|| c.LastName.ToLower().Contains(query.ToLower()));
return list.ToList();
}
When I navigate to http://localhost:50139/contacts/index?query=, I get an empty list. Having stepped through the code it is apparent that the query parameter is converted to an empty string value.
To ensure the search works, I have the following tests and all of them pass:
GetContacts_SearchByFirstName_ShouldReturnFilteredList
GetContacts_SearchByLastName_ShouldReturnFilteredList
GetContacts_SearchWithCapitalLetters_ShouldReturnFilteredList
GetContacts_SearchWithNullQuery_ShouldReturnAllContacts
In particular, the following test runs the function with empty string, which also passes successfully.
[TestMethod]
public void GetContacts_SearchWithEmptyString_ShouldReturnAllContacts()
{
var contactList = new List<Contact>()
{
// Construct new contact with first and last name and associated user id.
new Contact("e", "b",_userId ),
new Contact("c", "b",_userId ),
new Contact("a", "b",_userId ),
new Contact("d", "b",_userId )
};
_mockContacts.SetSource(contactList);
var result = _repository.GetContacts(_userId, "");
result.Count().Should().Be(4);
}
I have 3 contacts in the database and I can see all of them when I don't pass the query parameter. I would appreciate if you could point out why the controller action returns an empty list.
When you pass an empty string to the query parameter, the condition
if(query!=null) fails and the line below that
list = list.Where(c => c.FirstName.ToLower().Contains(query.ToLower())
|| c.LastName.ToLower().Contains(query.ToLower()));
gets executed, which checks the database for an entry with empty string in the LastName. This condition never gets satisfied and hence your list gets overridden with an empty list.
change if (query != null) to if (!string.IsNullOrEmpty(query))

Linq select from CRM public view

I have searching for a while now, but couldn't find how to query from public view. For example, I have predefined public view called Active Accounts and I want data from it.
So far I only know this way, but that not include any views:
using (var xrm = new XrmServiceContext("Xrm"))
{
var activeAccounts = from a in xrm.AccountSet
where a.StateCode == 0
select new { a.Id, a.Name };
// TODO ...
}
But I would like to do it like this (not working, ActiveAccountsView not exist, it's pseudo):
using (var xrm = new XrmServiceContext("Xrm"))
{
var activeAccounts = from a in xrm.ActiveAccountsView
select new { a.Id, a.Name };
// TODO ...
}
Is this even possible?
The query definitions of public views are stored in the savedquery entity, that can be queried using common techniques.
Out-of-the-box views are stored with a fixed ID, so querying Active Accounts on the OrganizationServiceContext object could be done in the following way:
private static IEnumerable<Entity> GetActiveAccounts(OrganizationServiceContext serviceContext)
{
string fetchXml = serviceContext
.CreateQuery("savedquery")
.Where(sq =>
sq.GetAttributeValue<Guid>("savedqueryid") == new Guid("00000000-0000-0000-00AA-000010001002"))
.Select(sq => sq.GetAttributeValue<string>("fetchxml"))
.First();
var request = new RetrieveMultipleRequest
{
Query = new FetchExpression(fetchXml)
};
var response = (RetrieveMultipleResponse) serviceContext.Execute(request);
return response.EntityCollection.Entities;
}
It is not possible to use LINQ here. LINQ relies on the QueryExpression class, but does not implement all its capabilities (OUTER JOIN is a painful omission for example). So, while it is possible to convert a LINQ query to a QueryExpression, the other way around is not.
Paging can be applied by editing the Fetch XML string, but if that is too much hassle, you can also consider to convert the Fetch XML to a QueryExpression and apply paging on that object:
private IEnumerable<Entity> GetActiveAccounts(int pageNumber)
{
string fetchXml = _serviceContext
.CreateQuery("savedquery")
.Where(sq =>
sq.GetAttributeValue<Guid>("savedqueryid") == new Guid("00000000-0000-0000-00AA-000010001002"))
.Select(sq => sq.GetAttributeValue<string>("fetchxml"))
.First();
var conversionRequest = new FetchXmlToQueryExpressionRequest
{
FetchXml = fetchXml
};
var response = (FetchXmlToQueryExpressionResponse)_serviceContext.Execute(conversionRequest);
response.Query.PageInfo = new PagingInfo { Count = 1, PageNumber = pageNumber };
var queryRequest = new RetrieveMultipleRequest
{
Query = response.Query
};
var result = (RetrieveMultipleResponse) _serviceContext.Execute(queryRequest);
return result.EntityCollection.Entities;
}
Additional advantage of the QueryExpression vs. Fetch XML is that it is processed in a bit more efficient way.
The very same can be done with user defined views; these views are stored in the userquery entity. The only difference here is you cannot rely on a fixed view ID. Instead you would need to filter your query on querytype, name, returnedtypecode, ownerid and/or other criteria.
Dynamics CRM also has an OrganizationRequest that allows you to execute the savedquery immediately. However, it returns its result as a resultset XML string, so you would still need to deserialize the response. (A nice example can be found here.) Also, I am not sure if it is possible to limit the result set to a specific page when using the ExecuteByIdSavedQueryRequest:
var request = new ExecuteByIdSavedQueryRequest
{
EntityId = new Guid("00000000-0000-0000-00AA-000010001002")
};
var response = (ExecuteByIdSavedQueryResponse)serviceContext.Execute(request);
string resultset = response.String;

Linq query Contains method with where condition with case sensitive less search

I am trying get the data which is contains single word with in the word.Like below query.
List<Models.tbluser> memberslist = new List<Models.tbluser>();
var obct = (from memlist in objcontext.tblusers
where memlist.logname.Contains(member)
select new
{
userid = memlist.userid,
logname = memlist.logname,
decription = memlist.description
}).ToList();
foreach (var item in obct)
{
memberslist.Add(new tbluser
{
userid = item.userid,
logname = item.logname,
description = item.decription
});
}
return Json(memberslist);
But here my problem is i need to search with out case sensitive.
For example
If i search with 'a' i need to get data like Admin,Administrator,User Data.
But i am not getting all these because i am searching with Contains() method.Please let me know how can i get all value either the search value is case sensitive less also.
Change your where condition to be:
memlist.logname.ToUpper().Contains(member.ToUpper())
As a side note, you can shorten your query a bit (you don't need to create an intermediary list):
var memberslist = objcontext.tblusers
.Where(x => x.logname.ToUpper().Contains(member.ToUpper())
.AsEnumerable()
.Select(x => new tbluser
{
userid = x.userid,
logname = x.logname,
decription = x.description
})
.ToList();
return Json(memberslist);
You can change them to Lower or Upper Case when checking the condition using ToLower() or ToUpper():
var obct = (from memlist in objcontext.tblusers
where memlist.logname.ToLower().Contains(member.ToLower())
select new
{
userid = memlist.userid,
logname = memlist.logname,
decription = memlist.description
}).ToList();

BaseQuery class missing in new NEST dll version NEST.1.1.2

What is the replacement of BaseQuery class in new version.
I couldn't find it anywhere.
My problem is how to generate syntax in c# for the search criteria as:
public class TextSearch
{
public string Headline {get;set;}
public string Summary {get;set;}
}
I need to search using text 'you', against two column as OR operator, Column 1 summary and Column 2 headline.
Earlier I was doing,
var orQuery = new List<BaseQuery>();
if (!string.IsNullOrEmpty(searchtext))
{
orQuery .Add(Query<TextSearch>.Terms("headline", searchOptions.text.ToLower().Split(' ')));
orQuery .Add(Query<TextSearch>.Terms("summary", searchOptions.text.ToLower().Split(' ')));
}
var finalQuery = new List<BaseQuery>();
finalQuery .Add(Query<TextSearch>.Bool(o => o.Should(orQuery.ToArray())));
Now this doesn't work.
Is there any better syntax for searching in new version.
The search criteria should using LIKE with OR,
e.g. summary LIKE '%you%' OR headling LIKE '%you%'
The documentation on the breaking changes in NEST 1.0 is pretty complete:
http://nest.azurewebsites.net/breaking-changes.html
We renamed BaseQuery to QueryContainer
The query can be:
client.Search<TextSearch>(s=>s
.Query(q=>
q.Terms("headline", words)
|| q.Terms("summary", words)
)
)
If words is empty or null that part is not rendered see the conditionless query section here:
http://nest.azurewebsites.net/nest/writing-queries.html
#Martijn Laarman
Since we have numerous filter criteria that will be dynamic based on user selected filter,
I'm constructing Filter Query in amethod based on user slelcted filter and then pass it to Search<> method as:
QueryContainer mainQuery = null;
if (!string.IsNullOrEmpty(searchOptions.SearchText))
{
var headline = Query<T>.Terms("headline", searchOptions.Headline.ToLower());
var summary = Query<T>.Terms("fullSummary", searchOptions.Summary.ToLower());
mainQuery &= (headline || summary);
}
if (searchOptions.FromDate != DateTime.MinValue && searchOptions.ToDate != DateTime.MinValue)
{
var dateFilter = Query<T>.Range(
r => r.OnField("processedDate").GreaterOrEquals(searchOptions.FromDate, ElasticDateFormat).LowerOrEquals(searchOptions.ToDate, ElasticDateFormat));
mainQuery &= dateFilter;
}
var result = Client.Search<T>(s => s.Query(mainQuery ).Size(Int32.MaxValue));
Here Client is a property that returns ElasticClient object.
Hope thats the correct way of doing.

Passing parameter to LINQ query

I have a method like below:
public void GetUserIdByCode(string userCode)
{
var query = from u in db.Users
where u.Code == userCode // userCode = "LRAZAK"
select u.Id;
var userId = query.FirstOrDefault(); // userId = 0 :(
}
When I ran the code, I got the default value of 0 assigned to userId meaning the Id was not found.
However, if I changed the userCode with a string like below, I will get the value I want.
public void GetUserIdByCode(string userCode)
{
var query = from u in db.Users
where u.Code == "LRAZAK" // Hard-coded string into the query
select u.Id;
var userId = query.FirstOrDefault(); // userId = 123 Happy days!!
}
My question is why passing the parameter into the LINQ query does not work?
When I stepped into the code, I got the SQL statement like so:
// Does not work...
{SELECT "Extent1"."LOGONNO" AS "LOGONNO"FROM "DEBTORSLIVE"."DEBTORS_LOGONS" "Extent1"WHERE ("Extent1"."LOGONCODE" = :p__linq__0)}
The hard-coded LINQ query (the working one) gives an SQL statement as below:
// Working just fine
{SELECT "Extent1"."LOGONNO" AS "LOGONNO"FROM "DEBTORSLIVE"."DEBTORS_LOGONS" "Extent1"WHERE ('LRAZAK' = "Extent1"."LOGONCODE")}
What would be the solution?
As a work-around, I use Dynamic Linq.
The code below is working for me.
public void GetUserIdByCode(string userCode)
{
string clause = String.Format("Code=\"{0}\"", userCode);
var userId = db.Users
.Where(clause)
.Select(u => u.Id)
.FirstOrDefault();
}
The database query returns an object of User with Code and Id as properties. This is defined in one of my classes.
Here is syntax that will work to pass an argument to a LINQ query.
Not sure how many people will be searching this topic so many years later, but here's a code example that gets the job done:
string cuties = "777";
// string collection
IList<string> stringList = new List<string>() {
"eg. 1",
"ie LAMBDA",
"777"
};
var result = from s in stringList
where (s == cuties)
select s;
foreach (var str in result)
{
Console.WriteLine(str); // Output: "777"
}

Categories