I'm attempting to remove white space from a post code field in a database so that when I compare it to the users input I'm comparing both strings with no spaces in the post code at all so it shouldn't matter how the post code is entered.
This is my LINQ query with the replace function that doesn't appear to be working:
List<SchoolReferanceDTO> res = db.SchoolReferences.Where(x => x.SchoolReferencePostcode.Replace(" ", "").Contains(Postcode)).Select(x => new SchoolReferanceDTO()
{
SchoolReferenceSchoolId = x.SchoolReferenceSchoolId,
SchoolReferenceEstablishmentName = x.SchoolReferenceEstablishmentName,
SchoolReferenceStreet = x.SchoolReferenceStreet,
SchoolReferenceLocality = x.SchoolReferenceLocality,
SchoolReferenceAddress3 = x.SchoolReferenceAddress3,
SchoolReferenceTown = x.SchoolReferenceTown,
SchoolReferenceCounty = x.SchoolReferenceCounty,
SchoolReferencePostcode = x.SchoolReferencePostcode,
SchoolReferenceEmail = x.SchoolReferenceEmail
}).ToList();
And the string I'm comparing it to:
postcode = postcode.Replace(" ", string.Empty);
One approach is to drop Replace, and use LIKE instead. Since postal codes are generally short, you could transform the target code ST14BJ to %S%T%1%4%B%J% (demo), and use LIKE operator:
var postPattern = Regex.Replace(postcode, "(?<=.|^)(?=.|$)", "%");
List<SchoolReferanceDTO> res = db.SchoolReferences
.Where(x => SqlFunctions.PatIndex(postPattern, x.SchoolReferencePostcode) >= 0)
.Select(...);
Related
I am trying to so the following:
var routines = con.Select<Table>(con.From<Table>().OrderBy(p => p.Field1).ThenBy(i => i.Field2));
The above works perfectly. But I want a rather more generic approach and parse a string like sort="field1,field2". I have the following code:
int sortFieldCount = 0;
var itemsq = con.From<Table>();
foreach (var name in orderByField.Split(',')) {
if(sortFieldCount == 0)
itemsq = sortOrderAscending ? itemsq.OrderBy(name) : itemsq.OrderByDescending(name);
else
itemsq = sortOrderAscending ? itemsq.ThenBy(name) : itemsq.ThenByDescending(name);
sortFieldCount++;
}
But the above code seems to overwrite the first OrderBy. Is there a solution to such a problem?
Thanks
Other ways you can perform multiple Order By's with ServiceStack.OrmLite include:
var orderByAnonType = db.Select(db.From<Track>().OrderBy(x => new { x.Album, x.Name }));
var orderByString = db.Select(db.From<Track>().OrderByFields("Album","Name"));
// Use `-` prefix to inverse sort order, e.g. Album Descending
var orderByString = db.Select(db.From<Track>().OrderByFields("-Album","Name"));
var orderByArray = db.Select(db.From<Track>().OrderBy(x => new[]{ "Album","Name" }));
So you could get a flexible OrderBy like AutoQuery's OrderBy with:
var fields = orderByString.Split(',', StringSplitOptions.RemoveEmptyEntries);
q.OrderByFields(fields);
Here's a live example of this you can play around with on gistlyn.com
There is a couple problems in the accepted answer I'd like to address.
First is the possibility of SQL injection attacks. ServiceStack does not fully validate what you pass in to the list of sort columns. While it will detect some of the more obvious attacks, you could still slip in things like calls to stored functions.
The second problem is descending sorts. It's not obvious from the API, but you can pass in "columnName DESC" rather than just "columnName". In fact, this is how it is able to support "Album,Name", it just passes it directly to SQL with the barest amount of validation.
public IList<Employee> SortBy(string lastName, string sortByColumnA, bool isDescendingA, string sortByColumnB, bool isDescendingB)
{
if (!Utilities.EmployeeColumnNames.Contains(sortByColumnA))
throw new ArgumentOutOfRangeException(nameof(sortByColumnA), "Unknown column " + sortByColumnA);
if (!Utilities.EmployeeColumnNames.Contains(sortByColumnB))
throw new ArgumentOutOfRangeException(nameof(sortByColumnB), "Unknown column " + sortByColumnB);
var sortDirectionA = isDescendingA ? " DESC " : "";
var sortDirectionB = isDescendingB ? " DESC " : "";
using (var db = _dbConnectionFactory.OpenDbConnection())
{
return db.Select(db.From<Employee>().Where(x => x.LastName == lastName)
.OrderBy(sortByColumnA + sortDirectionA + "," + sortByColumnB + sortDirectionB)).ToList();
}
}
I have a db call that returns me an object. I use linq to cast that object how I want it
var result = queryResult.OrderBy(c => c.TariffName)
.Take(count)
.Select(c => new
{
Text = c.TariffName,
Key = c.TariffId,
Price = c.LineRental
});
var list = result.ToList();
I now want to add the line rental to the tariff name show that it shows like:
myTariff - 12.99
when I try and do this though I can make this change ok:
Text = c.TariffName + " - ",
but when I try and add the line rental I get problems that linq won't recognise the ToString(). I need it to look like:
Text = c.TariffName + " - " + c.LineRental.ToString(),
I understand that linq won't recognise the ToString() method from reading LINQ to Entities does not recognize the method 'System.String ToString()' method, and this method cannot be translated into a store expression but how do I change this given I can't set it as a string prior to the linq query?
Convert the query result to a list first then use select to make the toString work.
var result = queryResult.OrderBy(c => c.TariffName)
.Take(count);
var list = result.ToList().Select(c => new
{
Text = c.TariffName + " - " + c.LineRental.ToString(),
Key = c.TariffId,
Price = c.LineRental
});
What is happening linq trying to execute your select statement on the database query level, and it does not know how to transform your .Select lambda to select part of sql statement.
Easiest thing you can do is first query required fields, call .ToList() on query to execute it and perform projection after that.
var result = queryResult.OrderBy(c => c.TariffName)
.Take(count)
.Select(c => new
{
Text = c.TariffName,
Key = c.TariffId,
Price = c.LineRental
});
var list = result.ToList().Select(c=>new {
Text = string.Format("{0} - {1}", c.Text, c.Price),
Key=Key,
Price=Price
});
Hi I am looking for a simple way to et just the name after the CN value
CN=Andrew Adams,OU=Services,OU=Users,OU=GIE,OU=CSP,OU=STAFF,DC=example,DC=net
is there an easy way to do this? I am currently doing this:
ResultPropertyValueCollection manager = result.Properties["manager"];
string managerUserName = manager[0].ToString();
string[] managerNameParts = managerUserName.Split(',');
string managerName = managerNameParts[0].Substring(4);
Console.WriteLine("Manager Name:" + managerName);
but it feels kind of bad.
This is a great place to use Regular Expressions. Try this:
var text = "CN=Andrew Adams,OU=Services,OU=Users,OU=GIE,OU=CSP,OU=STAFF,DC=example,DC=net";
var match = Regex.Match(text, #"CN=([^,]+)");
if (match.Success) return match.Groups[0].Value;
The expression CN=([^,]+) will look for the text CN= followed by one or more non-commas, and will stick that part of it into Groups[0].
You can do this:
var name = "CN=Andrew Adams,OU=Services,OU=Users,OU=GIE,OU=CSP,OU=STAFF,DC=example,DC=net"
.Split(',')[0].Split('=')[1];
Demo
What it does is splits on , and takes the first element and then splits it by = and takes the second element.
If you cannot have the same format, you can do a regex:
Regex.Match(name,#"(?<=CN=)[^,]+").Value;
Another option, using LINQ.
If the name/value pair exists anywhere in the string, you'll get it; if not, managerName will be null.
var managerName = input.Split(',')
.Where(x => x.StartsWith("CN="))
.Select(x => x.Split('=')[1])
.SingleOrDefault();
I find doing it like this fairly easy to read:
var input = #"CN=Andrew Adams,OU=Services,OU=Users,OU=GIE,OU=CSP,OU=STAFF,DC=example,DC=net";
var items = input.Split(',');
var keyValues = items.Select(x =>
{
var split = x.Split('=');
return new { Key = split[0], Value = split[1] };
});
var managerName = keyValues.Single(x => x.Key == "CN").Value;
I've this C# code to query my MongoDB collection:
var query = myCollection.FindAll().AsQueryable();
if (!string.IsNullOrWhiteSpace(username))
query = query.Where(
x => x.User.FullName.IndexOf(username, StringComparison.OrdinalIgnoreCase) >= 0);
if (!string.IsNullOrWhiteSpace(productName))
query = query.Where(
x => x.Product.ProductName.IndexOf(productName, StringComparison.OrdinalIgnoreCase) >= 0);
query = query.Take(pageSize).Skip(pageSize*(pageNumber-1));
var itemCount=query.Count();
var result = query.ToList();
Due to low performance now I want to use a full-text search. I created text index for User.FullName and Product.ProductName and I started to write code like this:
var textSearchCommand = new CommandDocument
{
{ "text", myCollection.Name },
{ "search", username }
};
var commandResult = _database.RunCommand(textSearchCommand);
var result = commandResult.Response;
Now I'm stuck; How to specify the property name in the above syntax example? Is this the right way to do that?
A text index points to the document as a whole, not to the individual field where the match occurs. That means a text-search is always performed on all fields which are part of the text-index. You can not selectively only search for matches in one field.
But what you can do is further filter the result-set of the $text-operator with additional operators. You could, for example, use an additional $regex-operator to check if the string you searched for occurs in the field where you want it to be.
I have this c# code that builds a string of comma seperated matches for a service:
for (m = r.Match(site); m.Success; m = m.NextMatch())
{
found = found + "," + m.Value.Replace(",", "");
}
return found;
Output looks like: aaa,bbb,ccc,aaa,111,111,ccc
Now that code is on .NET 4.0 How can I use C# LINQ to remove duplicates?
Also, Any way to remove duplicates without changing order?
I found this sample code in another post, but not sure exactly how to apply it:
int[] s = { 1, 2, 3, 3, 4};
int[] q = s.Distinct().ToArray();
Thanks.
string[] s = found.Split(',').Distinct().ToArray()
Rewrite the code that builds the result to output it directly.
ie. rewrite this:
for (m = r.Match(site); m.Success; m = m.NextMatch())
{
found = found + "," + m.Value.Replace(",", "");
}
return found;
To this:
return (from Match m in r.Matches(site)
select m.Value.Replace(",", "")).Distinct().ToArray();
This will return an array. If you still want it back as a string:
return string.Join(", ", (from Match m in r.Matches(site)
select m.Value.Replace(",", "")).Distinct().ToArray());
You may or may not be able to remove the last .ToArray() from the last code there depending on the .NET runtime version. .NET 4.0 string.Join(...) can take an IEnumerable<string>, whereas previous versions requires an array.
This will return a string of comma seperated values without duplicates:
var result = string.Join(",",
r.Matches(site)
.Cast<Match>()
.Select(m => m.Value.Replace(",", string.Empty))
.Distinct()
);
this could be one possible solution:
var data = new List<string>();
for (m = r.Match(site); m.Success; m = m.NextMatch())
data.Add(m.Value.Replace(",", ""));
return String.Join(",", data.Distinct().ToArray());
You can achieve this in a single LINQ query
string strSentence = "aaa,bbb,ccc,aaa,111,111,ccc";
List<string> results = (from w in strSentence.Split(',') select w).Distinct().ToList();