Multi column lambda expression - c#

Upon completeing the tutorial here:
https://learn.microsoft.com/en-us/aspnet/mvc/overview/older-versions/getting-started-with-ef-5-using-mvc-4/sorting-filtering-and-paging-with-the-entity-framework-in-an-asp-net-mvc-application
I currently use the following
userAccesses = userAccesses.Where(s => s.employeeDetail.employeeNumber.ToUpper().Contains(searchValue.ToUpper()));
However I'd like to concatenate the knownas / surname columns and then do the contains on the concatenated items.
Could anyone explain/suggest an example syntax?
This is what I've attempted below but I'm certain my syntax is incorrect.
userAccesses = userAccesses.Where(s => s.employeeDetail.employeeNumber + " " + s.employeeDetail.knownas + " " + s.employeeDetail.surname).Contains(searchValue);
Thanks for the response everyone, final working version is below.
userAccesses.Where(x => (x.employeeDetail.employeeNumber + x.employeeDetail.knownas + x.employeeDetail.surname).Contains(searchValue));

You should go to this direction
public class Employee
{
public string knownas { get; set; }
public string userName { get; set; }
}
public void Test()
{
List<Employee> employess = new List<Employee>();
string searchvalue = "test";
var listEmplyer = employess.Where(x => (x.userName + x.knownas).Contains(searchvalue));
}

You'll simply need to concatenate the string and call Contains on that string.
userAccesses
.Where(s => $"{s.employeeDetail.employeeNumber} {s.employeeDetail.knownas} {s.employeeDetail.surname}".Contains(searchValue))
If you need an enumerable of strings as the result of the expression, you can also choose to use the following:
userAccesses
.Select(s => $"{s.employeeDetail.employeeNumber} {s.employeeDetail.knownas} {s.employeeDetail.surname}")
.Where(s => s.Contains(searchValue))

Searching through concatenated column values is weird...
I'd suggest smth like this:
var filtered = userAccesses.Where(s => s.employeeDetail.employeeNumber.Contains(searchValue)
|| s.employeeDetail.knownas.Contains(searchValue)
|| s.employeeDetail.surname.Contains(searchValue));

Related

How to Convert List<'a> to other object list?

i want result linq statement convert to other list in Web Api
var data = Base_Tables.db.Lines.Find(id).Owner_Line.OrderByDescending(x => x.ID)
.Select(x => new { x.ID, Caption = x.Name1 + " " + x.Name2 + " " + x.Name3 })
.ToList();
List<HistoryLine> historyList = data as List<HistoryLine>();
Class HistoryLine
public class HistoryLine
{
public long ID { get; set; }
public string Caption { get; set; }
}
How to Convert ? , if can't convert statement, any way to fix this problem ?
Simply select into the object you want instead of an anonymous type.
var data = Base_Tables.db.Lines
.Find(id).Owner_Line
.OrderByDescending(x => x.ID)
.Select(x => new HistoryLine {ID = x.ID, Caption = x.Name1 + " " + x.Name2 + " " + x.Name3})
.ToList();
data is now a List<HistoryLine>

[System.DateTime])' has no supported translation to SQL

I want to execute a query like this:
List<supervisorAnswerQuesttionPres> temp =
(from i in dbconnect.tblAnswerLists
where i.StudentNum == studentNumber
select new supervisorAnswerQuesttionPres
{
answerList = _resAnswerList,
questionList = _resQuestionist,
date = ConvertToPersianToShow(i.dateOfAnswer.Value.Date)
}).OrderBy(i => i.date).ToList();
My class that this query is returned is something like this :
public class supervisorAnswerQuesttionPres
{
public string date { set; get; }
public List<string> questionList { set; get; }
public List<string> answerList { set; get; }
}
In this query i use a function to convert my Datetime to another presentation i use this function for this :
public string ConvertToPersianToShow(DateTime? datetime)
{
string date;
DateTime dt;
if (!datetime.HasValue) return "";
dt = datetime.Value;
// dt = datetime;
string year = Convert.ToString(persian_date.GetYear(dt));
string month = Convert.ToString(persian_date.GetMonth(dt));
string day = Convert.ToString(persian_date.GetDayOfMonth(dt));
if (month.Length == 1)
{
month = "0" + Convert.ToString(persian_date.GetMonth(dt));
}
if (day.Length == 1)
{
day = "0" + Convert.ToString(persian_date.GetDayOfMonth(dt));
}
Convert.ToString(persian_date.GetMonth(dt)) + "/" +
+ dt.Minute + ")";
date = year + "/" + month + "/" + day;
return date;
}
This function just convert my DateTime ,But when i execute the query i got this error:
Method 'System.String ConvertToPersianToShow(System.Nullable`1[System.DateTime])' has no supported translation to SQL.
It's trying to convert the query into SQL, but doesn't know how to convert the ConvertToPersianToShow method.
The solution is to call ToList() after the where clause to bring the entities into memory, then do the select:
var temp = dbconnect.tblAnswerLists
.Where(i => i.StudentNum == studentNumber)
.ToList() // <-- This will bring the data into memory.
.Select(i => new supervisorAnswerQuesttionPres
{
answerList = _resAnswerList,
questionList = _resQuestionist,
date = ConvertToPersianToShow(i.dateOfAnswer.Value.Date)
})
.OrderBy(i => i.date)
.ToList()
When calling ToList(), the query is translated into SQL, e.g. something like
SELECT * FROM <table> WHERE StudentNum = '<studentNumber>'
and executed against the database. When the data returns and you have it in memory, you can use LINQ to Objects to query and manipulate the data further.
NOTE! Generally you should be careful to call ToList before you've added at least a where clause, otherwise you'll end up fetching way too much data into memory.
try this:
var temp = (from i in dbconnect.tblAnswerLists
let pDate = ConvertToPersianToShow(i.dateOfAnswer.Value.Date)
where i.StudentNum == studentNumber
select new PresentClass.supervisorAnswerQuesttionPres
{
answerList = _resAnswerList,
questionList = _resQuestionist,
date = pDate
}).OrderBy(i => i.date).ToList();
reference: Method x has no supported translation to SQL
LINQ to SQL does not know how to translate a call your method 'ConvertToPersianToShow' into SQL in order to execute the where clause on the server. Your method does not exist on the server.
maybe something like this would help, but if it doesn't work you should fetch your data and then change it to the way you want it to be shown as
List<PresentClass.supervisorAnswerQuesttionPres> temp
= (from i in dbconnect.tblAnswerLists
let PDate=ConvertToPersianToShow(i.dateOfAnswer.Value.Date)
where i.StudentNum == studentNumber
select new PresentClass.supervisorAnswerQuesttionPres
{
answerList = _resAnswerList,
questionList = _resQuestionist,
date = PDate
}).OrderBy(i=>i.date).ToList();
As some people have noted, you can't run C# in SQL (well...lets ignore SQL CLR).
However your real problem comes from your poorly architected program.
Your data layer is doing display logic, and none of the Microsoft engineers expected that.
You should bring your data out of the database first. Then on your display logic use ConvertToPersianToShow(DateTime?) to bind to your view.
public class SupervisorAnswerQuestion
{
public DateTime? Date { set; get; }
public List<string> Questions { set; get; }
public List<string> Answers { set; get; }
}
public class SupervisorAnswerQuestionViewModel
{
public SupervisorAnswerQuestion SupervisorAnswerQuestion {get;set;}
public string DateFormated
{
get { return SupervisorAnswerQuestion.Date.ToString("yyyy/MM/dd");
}
}
Actual come to think of it. Scrap ConvertToPersianToShow, learn DateTime.ToString(string) for datetime formatting.

Concat or Join list of "names" in Linq

Using WCF RIA I have a query that returns a Query of names
public class WitnessInfo
{
[Key]
public Guid WCFId { get; set; }
public string witnessName { get; set; }
public string AllNames {get; set;}
}
Here's my Linq Query
[Query]
public IQueryable<WitnessInfo> getWitnessInfo(int? id)
{
IQueryable<WitnessInfo> witnessQuery = from witness in this.Context.witness
where witness.DAFile.Id == id
select new WitnessInfo
{
WCFId = Guid.NewGuid(),
witnessName = witness.Person.FirstName,
};
return witnessQuery;
}
I want to take all the names and return them in a single string i.e "John, James, Tim, Jones". Tried taking AllNames and looping through but that didn't work. Any suggestions?
First grab all of the information that you need in a single query, then use String.Join to map the collection of names to a single string:
var firstQuery = from witness in Context.witness
where witness.DAFile.Id == id
select new
{
WCFId = Guid.NewGuid(),
witnessName = witness.Person.FirstName,
Names = Context.witness.Select(w => w.FirstName),
})
.AsEnumerable(); //do the rest in linq to objects
var finalQuery = from witness in firstQuery
//do the string manipulation just once
let allNames = string.Join(", ", witness.Names)
select new WitnessInfo
{
WCFId = witness.WCFId,
witnessName = witness.witnessName,
AllNames = allNames,
});
By having the AllNames property in the WitnessInfo class, it is seems like you want each WitnessInfo object to contain the all of the squence names again and again repeatedly, and if this is your case then do it like that:
var names = (from witness in this.Context.witness
select witness.Person.FirstName).ToArray();
var allNames = string.Join(", ", names);
IQueryable<WitnessInfo> witnessQuery = from witness in this.Context.witness
where witness.DAFile.Id == id
select new WitnessInfo
{
WCFId = Guid.NewGuid(),
witnessName = witness.Person.FirstName,
AllNames = allNames
};
You can concatenate like this:
string.Join(", ", getWithnessInfo(666).Select(wq => wq.witnessName))
this.Context.witness.Select(a => a.Person.Firstname).Aggregate((a, b) => a + ", " + b);

How to compare and select values from string using Linq?

Had a class:
class filedate
{
public int id;
public string fname;
}
Fill my list with values:
List<filedate> List = ReadList(sqlFiles);
string[] FolderFiles = System.IO.Directory.GetFiles(path2Copy);
Trying to get results:
var results = List.Where(filedate =>
FolderFiles.Any(x=>Path.GetFileNameWithoutExtension(x) ==
Path.GetFileNameWithoutExtension(filedate.fname)));
I have the same files in List and FolderFiles, but get no results in results. I am a newbie to Linq. Where is the problem?
update:
List: (count) > 1000
for example:
<1023, 'tr_F2opervag_2808_1644.dat'>
FolderFiles example:
"\\domain.corp.dns\share\folder\tr_F2opervag_2808_1644.dat"
Update 2:
found out my mistake! Comment with intersection was helpful! This code is working:
var results = List.Where(
(filedate x) =>
{
return ! FolderFiles.Any(xxx =>
Path.GetFileNameWithoutExtension(xxx) ==
Path.GetFileNameWithoutExtension(x.fname));
});
You're code works fine for me so there's something wrong with the format of your data in the List coming back from the database.
Post an example of an fname value from the filedata object. It needs to be a valid fully qualified path.
This works fine for me.
public class FileData{
public int id;
public string fname;
}
void Main()
{
List<FileData> list = new List<FileData>{
new FileData { id=1, fname="C:\\install.res.1042.dll"},
new FileData { id=2, fname="C:\\install.res.1041.dll" },
new FileData { id=3, fname="C:\\install.res.9999.dll"}
};
string[] FolderFiles = System.IO.Directory.GetFiles("C:\\");
var results = list
.Where(fd =>
FolderFiles.Any(x=>Path.GetFileNameWithoutExtension(x) ==
Path.GetFileNameWithoutExtension(fd.fname)));
Console.WriteLine(results);
}
If you need to find the difference this should work. This is available via Enumerable.Except.
var dbFiles = ReadList(sqlFiles);
var dbFilePaths =
dbFiles.Select(fdate =>
Path.GetFileNameWithoutExtension(fdate.fname).ToLower());
var fsFilePaths =
Directory
.GetFiles(path2Copy)
.Select(filePath =>
Path.GetFileNameWithoutExtension(filePath).ToLower());
var diff =
dbFilePaths
.Except(fsFilePaths)
.Join(dbFiles,
filePath => filePath,
fdate => fdate.fname,
(filePath, fdate) => fdate)
.ToList();

FileHelpers: Searching into results

I use the powerful FileHelpers Library. But is there a built-in way to search over the generated objets.
var engine = new FileHelperEngine<Text>();
var res = engine.ReadFile("myfile.csv");
string result = res["key"].value;
My csv is like : key;value
I mean, is it possible not to access objects with the array [0], [1], [12]...
maybe like in the code example.
Thanks a lot !
You can convert your resulting array to a dictionary via LINQ with:
var dictionary = validRecords.ToDictionary(r => r.Key, r => r.Value);
The following complete program demonstrates the approach.
[DelimitedRecord(",")]
public class ImportRecord
{
public string Key;
public string Value;
}
class Program
{
static void Main(string[] args)
{
var engine = new FileHelperEngine<ImportRecord>();
string fileAsString = #"Key1,Value1" + Environment.NewLine +
#"Key2,Value2" + Environment.NewLine;
ImportRecord[] validRecords = engine.ReadString(fileAsString);
var dictionary = validRecords.ToDictionary(r => r.Key, r => r.Value);
Assert.AreEqual(dictionary["Key1"], "Value1");
Assert.AreEqual(dictionary["Key2"], "Value2");
Console.ReadKey();
}
}

Categories