Passing object to linq result - c#

I get an item from the list to manuplate it.
App.CurrentQuestion = App.AllQuestionList[dataSourceRowIndex];
After manuplations I save new data to database and get back from database into App.CurrentQuestion, so App.CurrentQuestion's list reference breaks. I want to update list and trying to focus selected item by linq
App.AllQuestionList
.Where(q => q.qID == App.CurrentQuestion.qID)
.FirstOrDefault() = App.CurrentQuestion;
but I get an error like "The left-hand side of an assignment must be a variable, property or indexer"
I can use this method
for (int i = 0; i < App.AllQuestionList.Count; i++)
{
if (App.AllQuestionList[i].qID == App.CurrentQuestion.qID)
{
App.AllQuestionList[i] = App.CurrentQuestion;
break;
}
}
but looking for an alternative method. Or is there any faster method?

You shouldn't have to do anything, since it's by reference.
App.CurrentQuestion = App.AllQuestionList[dataSourceRowIndex];
Whatever change you make in App.CurrentQuestion should be reflected in the App.AllQuestionList
App.AllQuestionList[App.AllQuestionList.IndexOf(App.AllQuestionList.
.Where(q => q.qID == App.CurrentQuestion.qID)
.First())] = App.CurrentQuestion;
Edit: you can just use the IndexOf to find the index of the object you wanted to find by LINQ query

Related

How to bind data to DTO attribute based on a condition?

I'm trying to bind data to a variable known as CurrentControlled that is defined in my DTO (Data transfer object), The issue is that i want to assign a string based on what data is returned from the database. In this case i have a table in my database known as RiskActions which has a column known as ActionCompleteDate, if the data inside ActionCompleteDate has date value in it than the string assigned to CurrentControlled should be 'Current', whereas if there is no date present inside ActionCompleteDate then the value for CurrentControlled should be Controlled.
I have tried assigning a condition to CurrentControlled but for some reason the compiler gives me an error.
var actions = dataContext.RiskInstances.Where(riskInstancePredicate.Compile());
actions = actions
.OrderBy(a => a.RiskInstanceID2)
.ThenBy(a=> a.Issue.Question);
List<RiskDTO> results = actions
.Select(ra => new RiskDTO
{
CurrentControlled = if(ra.RiskActions.Where(m => m.ActionCompleteDate == null)) {
TerminologyFactor.Parse("{Current}",TerminologyFactor.RMMonitor)
}
else {
TerminologyFactor.Parse("{Controlled}",TerminologyFactor.RMMonitor)
}
})
You need to use the conditional operator. Also, this is a guess because I don't know your data structure here, but you likely need to use Any instead of Where as it returns a boolean you can use as the condition:
List<RiskDTO> results = actions
.Select(ra => new RiskDTO
{
CurrentControlled = ra.RiskActions.Any(m => m.ActionCompleteDate == null))
? TerminologyFactor.Parse("{Current}",TerminologyFactor.RMMonitor)
: TerminologyFactor.Parse("{Controlled}",TerminologyFactor.RMMonitor)
}

Get the first item property with lambda expression

In C#, I'm going to use lambda expression, I have such a code
var item = dbContext.Products.ToList();
How can i get a property of Product table.
try this
var item = dbContext.Products.FirstOrDefault().Name;
With Lamba expression normally you can access and read information from "list" or in this case, IQueryable objects.
With your code you can access to objects with something like this:
var item = dbContext.Products.FirstOrDefault();
// item may be null if products table is empty
if (item != null)
{
// now you can access at object properties (example)
var data = item.PropertyData;
}
Your question may open others way that including reflection for exploring object without well known class definition...
If you want to get the property for each product with lambda expression, then you should make a lambda expression like x => x.Prop when you do your query
if (dbContext.Products != null){
var list = dbContext.Products.ToList();
var query = list.Select(x => x.Prop //your property will appear here...
}

Asp.Net Mvc delete columns from database table

I am trying to delete all table data where username = current user name. But there is some error on lambda expression and conversion."Cannot convert source type to target type. Any help?
public JsonResult DeleteChatMessages(int id)
{
string toId = Session["SessionUserName"].ToString();
tblChat tblchats = _obj.tblChat.Where(p => p.ToId == toId);
_obj.tblChat.Remove(tblchats);
_obj.SaveChanges();
return this.Json(true, JsonRequestBehavior.AllowGet);
}
I am assuming you are expecting only one object to return from the Where filter.
Change your line as,because as per this . The Where clause returns an IEnumerable<TSource>. And you are assigning that to the non IEnumerable object.
tblChat tblchats = _obj.tblChat.FirstOrDefault(p => p.ToId == toId)
and you also might want to check for the Null, before removing it from the tblChat.
If you are expecting more than one object to match the filter and want to remove all of them then use #tmg approach.
_obj.tblChat.RemoveRange(_obj.tblChat.Where(p => p.ToId == toId).ToList());
Filter the "chats" you want.
var tblchats = _obj.tblChat.Where(p => p.ToId == toId).ToList();
After iterate throught them and remove.
foeach(chat in tblchats){
_obj.tblChat.Remove(chat);
}
_obj.SaveChanges();

c# copied property loses reference when referenced object is removed from list

Example
Have a look at the following code:
private void DeDuplicateOrganisations()
{
var profileOrgs = _organisations.Where(o => o.ExistsInProfile).ToList();
var kvkOrgs = _organisations.Where(o => !o.ExistsInProfile).ToList();
profileOrgs.ForEach(o =>
{
var duplicate = kvkOrgs.FirstOrDefault(k => k.KvK == o.KvK || k.Title == o.Title);
if (duplicate != null)
{
o.CompanyInfoOrganisation = duplicate.CompanyInfoOrganisation;
o.ExistsInBoth = true;
kvkOrgs.Remove(duplicate);
}
});
_organisations = profileOrgs.Concat(kvkOrgs).OrderBy(o => o.Title).ToList();
}
In this example the property CompanyInfoOrganisation (simply a get; set; property) is copied when an organisation is considered a duplicate. This all works as expected, duplicates are nicely deduplicated.
Also this is true inside this message:
_organisations.First(o => o.ExistsInBoth).CompanyInfoOrganisation != null;
Problem
Now I bind the _organisations list to a listbox
lbxCompanies.DataSource = null;
lbxCompanies.DataSource = _organisations;
lbxCompanies.DisplayMember = "Title";
lbxCompanies.SelectedIndex = -1;
and later on get the selected value:
var org = lbxCompanies.SelectedValue as Organisation;
gbxCompanyInfo.Visible = org != null;
if (gbxCompanyInfo.Visible)
if (org.CompanyInfoOrganisation != null)
// NEVER GETS HERE (but gbxComanpyInfo is visible)
If I try to read the CompanyInfoOrganisation property I always get null while I know the property was set.
Question
What is happening here? How come the property reference is destroyed? How can I prevent this from happening?
The reference you're using only has immediate scope and as soon as the query ends it exits scope and your reference disappears. So when you bind later, the reference is exactly right -- null.
profileOrgs.ForEach(o =>
{
// Right here -- var duplicate has scope ONLY within your query.
// As soon as the query is executed it leaves scope and the reference
// pointer will be null
var duplicate = kvkOrgs.FirstOrDefault(k => k.KvK == o.KvK || k.Title == o.Title);
if (duplicate != null)
{
o.CompanyInfoOrganisation = duplicate.CompanyInfoOrganisation;
o.ExistsInBoth = true;
kvkOrgs.Remove(duplicate);
}
});
Because you're using a class, you need to perform a deep MemberwiseClone on it to get a NEW copy of the object:
o.CompanyInfoOrganisation = (YourInfoType)duplicate.CompanyInfoOrganisation.MemberwiseClone();
When you load the data, load the CompanyInfoOrganisation property along with the root entity; that way it will be already loaded into memory. If using LINQ to SQL, you load via DataLoadOptions, and pass this to the context. If using Entity Framework, you use the Include method in the LINQ query.
It might have to do with capturing of variables inside the lambda. Try substituting the .ForEach to a regular foreach().
Or maybe the CompanyInfoOrganisation in duplicate was null to begin with.
The problem was I used string.Join() to show the values, and the first value to join was null (which is really annoying), resulting in an empty string, leaving me thinking the property was null. However it turned out the property was not null, but has a perfectly valid reference to the object needed. Using the debugger with a little more care would have saved me an hour or so...
Sorry!

Linq deferred execution with local values

I've been experimenting with Linq to see what it can do - and I'm really loving it so far :)
I wrote some queries for an algorithm, but I didn't get the results I expected... the Enumeration always returned empty:
case #1
List<some_object> next = new List<some_object>();
some_object current = null;
var valid_next_links =
from candidate in next
where (current.toTime + TimeSpan.FromMinutes(5) <= candidate.fromTime)
orderby candidate.fromTime
select candidate;
current = something;
next = some_list_of_things;
foreach (some_object l in valid_next_links)
{
//do stuff with l
}
I changed the query declaration to be inline like this, and it worked fine:
case #2
foreach (some_object l in
(from candidate in next
where (current.toTime + TimeSpan.FromMinutes(5) <= candidate.fromTime)
orderby candidate.fromTime
select candidate))
{
//do stuff with l
}
Does anybody know why it doesn't work in case #1 ?
The way I understood it, the query wasn't evaluated when you declared it, so I don't see how there is a difference.
Changes to current will be captured, but the query already knows the value of next. Adding extra items to the existing list will make them show up in the query, but changing the value of the variable to refer to a different list entirely won't have any effect. Basically, if you mentally expand the query from a query expression into a "normal" form, any variable present in a lambda expression will be captured as a variable, but any variable present directly as an argument will be evaluated immediately. That will only capture the reference value of the variable, not the items present in the list, but it still means changing the variable value itself won't be seen. Your first query expands to:
var valid_next_links = next
.Where(candidate => (current.toTime + TimeSpan.FromMinutes(5) <= candidate.fromTime))
.OrderBy(candidate => candidate.fromTime);

Categories

Resources