Linq Converting String to List - c#

Hi I am getting the following error with my Linq query.
Cannot implicitly convert type 'System.Collections.Generic.List<string>'
to 'System.Collections.Generic.List<CTS.Domain.OCASPhoneCalls>'
I know what it means, but I'm unsure how to fix it. Can someone help me with my query? I'm really new to linq.
public List<OCASPhoneCalls> getPhoneLogs2()
{
using (var repo = new OCASPhoneCallsRepository(new UnitOfWorkCTS()))
{
List<OCASPhoneCalls> phone = repo.AllIncluding(p => p.OCASStaff)
.Where(y => y.intNIOSHClaimID == null)
.Select(w => w.vcharDiscussion.Substring(0, 100) + "...")
.ToList();
return phone;
}
}

You are selecting a single property with
.Select(w => w.vcharDiscussion.Substring(0, 100) + "...")
This would return you IEnumerable<string> and calling ToList would return you List<string> NOT List<OCASPhoneCalls>.
If you are returning formatted strings then your method return type should be List<string> like:
public List<string> getPhoneLogs2()
{
using (var repo = new OCASPhoneCallsRepository(new UnitOfWorkCTS()))
{
List<string> phone = repo.AllIncluding(p => p.OCASStaff)
.Where(y => y.intNIOSHClaimID == null)
.Select(w => w.vcharDiscussion.Substring(0, 100) + "...")
.ToList();
return phone;
}
}

You are selecting a List<string> but you are declaring a List<OCASPhoneCalls>, i assume you want to shorten the vcharDiscussion:
List<OCASPhoneCalls> phones = = repo.AllIncluding(p => p.OCASStaff)
.Where(p => p.intNIOSHClaimID == null)
.ToList();
phones.ForEach(p => p.vcharDiscussion = p.vcharDiscussion.Length > 100 ?
p.vcharDiscussion.Substring(0, 100) + "..." :
p.vcharDiscussion);
return phones;
Edit: "I'm getting a null error. vcharDiscussion is coming up null"
Then you need to check that:
phones.ForEach(p => p.vcharDiscussion =
p.vcharDiscussion != null && p.vcharDiscussion.Length > 100 ?
p.vcharDiscussion.Substring(0, 100) + "..." :
p.vcharDiscussion ?? "");

`.Select(w => w.vcharDiscussion.Substring(0, 100) + "...")`
because select it's projection and it will return a list of string and your method expect to return
List<OCASPhoneCalls>

Related

How to increase SQL parser speed that using TSqlParser?

In my code, I have several SQL scripts that I want to parse using TSql130Parser in order to refactor them. But this process takes a long time - is there a way to increase the speed of this?
Also I have another question that TSql130Parser can get bulk as parameter? If it is possible, how can I do it?
This is my method that I use for parsing procedures by passing content of procedure as query in method parameter:
public string ParseProcedureQuery(string query, out string procedureName)
{
procedureName= "";
try
{
TSql130Parser parser = new TSql130Parser(true);
IList<ParseError> errors;
var fragments = parser.Parse(new System.IO.StringReader(query), out errors);
var proc = fragments.ScriptTokenStream.Where(x => x.TokenType == TSqlTokenType.Proc || x.TokenType == TSqlTokenType.Procedure).Select(x => x.Text).FirstOrDefault();
if (proc == null)
return string.Empty;
var index = fragments.ScriptTokenStream.FindIndex(c => c.Text == proc);
var name = fragments.ScriptTokenStream
.Select((value, ind) => new { value, index = ind })
.Where(pair => pair.index > index && pair.value.TokenType != TSqlTokenType.WhiteSpace)
.Select((value, ind) => new { value.value.Text, index = ind }).Where(y => y.index < 3).Select(p => p.Text);
procedureName = string.Join(String.Empty, name);
var processedQuery = string.Join(" ", fragments.ScriptTokenStream
.Where(x => x.TokenType != TSqlTokenType.MultilineComment)
.Where(x => x.TokenType != TSqlTokenType.SingleLineComment)
.Where(x => x.TokenType != TSqlTokenType.WhiteSpace)
.Select(x => x.Text));
return processedQuery;
}
catch
{ }
}

List.OrderBy define order in a variable

I have a list containing objects :
class MyType
{
String Name;
String Address;
DateTime BirthDay;
}
List<MyType> myList;
I want to write a function working like this :
public void SortList(int value)
{
// orderValue => this is the variable I need
if (value == 0)
orderValue = MyType.Name; // Sort list by Name
else if (value == 1)
orderValue = MyType.Address; // Sort list by Address
else if (value == 1)
orderValue = MyType.BirthDay; // Sort list by BirthDay
if (orderValue != null)
{
List<MyType> sortedList = myList.OrderBy(orderValue).ToList();
if (Enumerable.SequenceEqual(myList, sortedList))
sortedList = myList.OrderByDescending(orderValue).ToList();
myList = sortedList;
}
}
How can I write my orderValue to make this code working ?
This is just a synthesis of my code, I can provide more details if needed.
OrderBy can accept Func and you can have variable like this
Func<Person, string> orderFunc = x => x.Name;
if (value == 0)
orderFunc = x => x.Name;
else if (value == 1)
orderFunc = x => x.Address;
myList = myList.OrderBy(orderFunc).ToList();
You have several ways of doing it. For example, you can add OrderBy clause inside your conditional statement, like this:
IEnumerable<MyType> data = myList;
if (value == 0)
data = data.OrderBy(x => x.Name); // Sort list by Name
else if (value == 1)
data = data.OrderBy(x => x.Address); // Sort list by Address
res = data.ToList();
You can also do it in a single statement:
res = myList
.OrderBy(x => value == 0 ? x.Name : "")
.ThenBy(x => value == 1 ? x.Address : "")
.ToList();
This is somewhat harder to read, but it will do the work on RDBMS side in EF or LINQ to SQL.
You can try
myList.OrderBy((x) => (value == 0 ? x.Name : x.Address));

Linq Combine two statements into one big statement (optimization)

I have a method which is using a lot of LINQ to set and match some values in a list of Tuple<string, int>.
Right now i'm still stuck with two foreach loops nested into eachother and i think it'd be possible to combine them into one gigantic LINQ query. I'm wondering what would be the best way to do this with optimization as a big condition.
This is the function i'm talking about:
private async void AddLocalChangesFromPendingOperations()
{
var pendingOperations = await this.operationsStorage.GetOperationsAsync();
var list = pendingOperations.
SelectMany(pendingOperation =>
pendingOperation.Settings, (pendingOperation, setting) =>
new { pendingOperation, setting })
.Where(a => a.setting.Key == "selection")
.Select(a => new Tuple<string, int>(
a.pendingOperation.DefinitionId,
Convert.ToInt32(a.setting.Value.ValueObject)))
.ToList();
foreach (var pendingChange in list)
{
var selection = await this.selectionsStorage.GetSelectionByIdAsync(pendingChange.Item2);
foreach (var selectionsViewModel in this.SelectionsList.Where(a => a.Name == selection.Name))
{
if (pendingChange.Item1 == "selection-add-animals")
{
selectionsViewModel.IsActive = true;
}
else if (pendingChange.Item1 == "selection-remove-animals")
{
selectionsViewModel.IsActive = false;
}
}
}
}
If possible i'd like to optimize the last two foreaches while using linq. I've tried something but i'm stuck on setting values in the current list...
I was doing this:
this.SelectionsList = this
.SelectionsList
.Where(a => a.Name == selection.Name)
.SingleOrDefault(
a => pendingChange.Item1 == "selection-add-animals" ? a.IsActive = true : a.IsActive = false
);
In general, LINQ is for querying items (Language Integrated Query). You could however do a query and then do a foreach at the end:
private async void AddLocalChangesFromPendingOperations()
{
var pendingOperations = await this.operationsStorage.GetOperationsAsync();
(await Task.WhenAll(pendingOperations
.SelectMany(pendingOperation =>
pendingOperation.Settings, (pendingOperation, setting) =>
new { pendingOperation, setting })
.Where(a => a.setting.Key == "selection")
.Select(a => Tuple.Create(a.pendingOperation.DefinitionId, Convert.ToInt32(a.setting.Value.ValueObject)))
.Select(async pendingChange => Tuple.Create(await this.selectionsStorage.GetSelectionByIdAsync(pendingChange.Item2)), pendingChange))
.SelectMany(tuple => this.SelectionsList.Where(a => a.Name == tuple.Item1.Name)
.Select(selectionsViewModel => Tuple.Create(selectionsViewModel, tuple.Item2))
.Select(tuple => Tuple.Create(tuple.Item1, tuple.Item2.Item1 == "selection-add-animals"))
.ToList()
.ForEach(tuple => tuple.Item1.IsActive = tuple.Item2);
}
Whether this is clearer than your original implementation is up for discussion (I don't think it is), but it would be one way of doing it.
NOTE: This was typed into the editor directly, there might be some minor syntax errors.
You can do something like:
this.SelectionsList = this.SelectionsList
.Where(a => a.Name == selection.Name)
.Select(a =>
{
a.IsActive = a.Name == selection.Name ? true:false;
return a;
}).ToList();

Cannot convert source type to System.Nullable<double>

Here's my script:
public PlainBrgDataSummaryComplete SummaryComputationPerTransSQLite(long ProgramID)
{
PlainBrgDataSummaryComplete result = new PlainBrgDataSummaryComplete();
DataSet dataSet = GetPlainBrgDataSQLite(ProgramID);
var abcde = dataSet.Tables["dataBridge"]
.AsEnumerable()
//.Where(a => Convert.ToDateTime(a["reportingDate"].ToString()) >= startOfWeek1 && Convert.ToDateTime(a["reportingDate"].ToString()) < endOfWeek1.AddDays(1))
.GroupBy(a => 1)
.Select(d =>
new PlainBrgDataSummaryTrans
{
transactionWk6 = d.Sum(a => a.Field<double?>("TranCount"))
}
).FirstOrDefault();
result.totaltransaction = new PlainBrgDataSummaryTrans
{
transactionWk6 = abcde;
};
return result;
}
I'm getting the error - Cannot convert source type to System.Nullable<double>. Specifically on the part transactionWk6 = abcde;
abcde is already a PlainBrgDataSummaryTrans type since you are projecting the select statement to it.
Try to use it like this:
result.totaltransaction = abcde;
return result;
Mihail Stancescu should solve the issue. However considering your return type you dont need the extra assignment. you can change code like below
public PlainBrgDataSummaryComplete SummaryComputationPerTransSQLite(long ProgramID)
{
DataSet dataSet = GetPlainBrgDataSQLite(ProgramID);
return dataSet.Tables["dataBridge"]
.AsEnumerable()
//.Where(a => Convert.ToDateTime(a["reportingDate"].ToString()) >= startOfWeek1 && Convert.ToDateTime(a["reportingDate"].ToString()) < endOfWeek1.AddDays(1))
.GroupBy(a => 1)
.Select(d =>
new PlainBrgDataSummaryTrans
{
transactionWk6 = d.Sum(a => a.Field<double?>("TranCount"))
}
).FirstOrDefault();
}

How to combine the multiple part linq into one query?

Operator should be ‘AND’ and not a ‘OR’.
I am trying to refactor the following code and i understood the following way of writing linq query may not be the correct way. Can somone advice me how to combine the following into one query.
AllCompany.Where(itm => itm != null).Distinct().ToList();
if (AllCompany.Count > 0)
{
//COMPANY NAME
if (isfldCompanyName)
{
AllCompany = AllCompany.Where(company => company["Company Name"].StartsWith(fldCompanyName)).ToList();
}
//SECTOR
if (isfldSector)
{
AllCompany = AllCompany.Where(company => fldSector.Intersect(company["Sectors"].Split('|')).Any()).ToList();
}
//LOCATION
if (isfldLocation)
{
AllCompany = AllCompany.Where(company => fldLocation.Intersect(company["Location"].Split('|')).Any()).ToList();
}
//CREATED DATE
if (isfldcreatedDate)
{
AllCompany = AllCompany.Where(company => company.Statistics.Created >= createdDate).ToList();
}
//LAST UPDATED DATE
if (isfldUpdatedDate)
{
AllCompany = AllCompany.Where(company => company.Statistics.Updated >= updatedDate).ToList();
}
//Allow Placements
if (isfldEmployerLevel)
{
fldEmployerLevel = (fldEmployerLevel == "Yes") ? "1" : "";
AllCompany = AllCompany.Where(company => company["Allow Placements"].ToString() == fldEmployerLevel).ToList();
}
Firstly, unless AllCompany is of some magic custom type, the first line gives you nothing.
Also I have a doubt that Distinctworks the way You want it to. I don't know the type of AllCompany but I would guess it gives you only reference distinction.
Either way here'w what I think You want:
fldEmployerLevel = (fldEmployerLevel == "Yes") ? "1" : "";
var result = AllCompany.Where(itm => itm != null)
.Where(company => !isfldCompanyName || company["Company Name"].StartsWith(fldCompanyName))
.Where(company => !isfldSector|| fldSector.Intersect(company["Sectors"].Split('|')).Any())
.Where(company => !isfldLocation|| fldLocation.Intersect(company["Location"].Split('|')).Any())
.Where(company => !isfldcreatedDate|| company.Statistics.Created >= createdDate)
.Where(company => !isfldUpdatedDate|| company.Statistics.Updated >= updatedDate)
.Where(company => !isfldEmployerLevel|| company["Allow Placements"].ToString() == fldEmployerLevel)
.Distinct()
.ToList();
Edit:
I moved Distinct to the end of the query to optimize the processing.
How about trying like this;
AllCompany = AllCompany .Where(company => (company => company.Statistics.Created >= createdDate)) && (company.Statistics.Updated >= updatedDate));
If every part of query is optional (like created date, last update date..) then you can build linq query string.
Here's a sneaky trick. If you define the following extension method in its own static class:
public virtual IEnumerable<T> WhereAll(params Expression<Predicate<T> filters)
{
return filters.Aggregate(dbSet, (acc, element) => acc.Where(element));
}
then you can write
var result = AllCompany.WhereAll(itm => itm != null,
company => !isfldCompanyName || company["Company Name"].StartsWith(fldCompanyName),
company => !isfldSectorn || fldSector.Intersect(company["Sectors"].Split('|')).Any(),
company => !isfldLocation || fldLocation.Intersect(company["Location"].Split('|')).Any(),
company => !isfldcreatedDate || company.Statistics.Created >= createdDate,
company => !isfldUpdatedDate || company.Statistics.Updated >= updatedDate,
company => !isfldEmployerLevel || company["Allow Placements"].ToString() == fldEmployerLevel)
.Distinct()
.ToList();

Categories