Below my code. It returns exception "InvalidCastException". And main question is - why?What is wrong?
Error text:
Unable to cast object of type
'WhereSelectListIterator`2[Monopolowy_beta.Gracz,Monopolowy_beta.Gracz]'
to type 'Monopolowy_beta.Gracz'.
namespace Monopolowy_beta
{
class Program
{
static void Main(string[] args)
{
List<Gracz> lista = new List<Gracz> { };
Gracz g1 = new Gracz();
Gracz g2 = new Gracz();
Gracz g3 = new Gracz();
g2.Id = 3;
lista.Add(g1);
lista.Add(g2);
lista.Add(g3);
g1 = GraczeTools.UstawAktywnegoGracza(lista, 3);
Console.ReadKey();
}
}
}
Error in these lines:
var docelowy = from item in listagraczy where (item.Id==ID && item.czyAktywny == true) select listagraczy[listagraczy.IndexOf(item) + 1];
gracz = (Gracz)docelowy;
namespace Monopolowy_beta
{
static class GraczeTools
{
public static Gracz UstawAktywnegoGracza(List<Gracz> listagraczy, int ID)
{
Gracz gracz = new Gracz();
if (ID == 4){
var docelowy = from item in listagraczy where (item.czyAktywny == true && item.Id == 3) select listagraczy[1];
gracz = (Gracz)docelowy;
}
if (ID != 4){
var docelowy = from item in listagraczy where (item.Id==ID && item.czyAktywny == true) select listagraczy[listagraczy.IndexOf(item) + 1];
gracz = (Gracz)docelowy;
}
return gracz;
}
}
}
var docelowy = from item in listagraczy
where (item.czyAktywny == true && item.Id == 3)
select listagraczy[1];
Let's examine this query. It finds all items which satisfy condition (yes, it will return sequence, not single item) and for each such item, it returns.. second element of listagraczy list. Yes, you don't have items, which matched your condition.
I think you should select item instead (this a range variable of your query), and apply FirstOrDefault to result, because by default query will return IEnumerable<Gracz> result.
var docelowy = (from item in listagraczy
where (item.czyAktywny == true && item.Id == 3)
select item).FirstOrDefault();
Which is better to write with fluent API:
var docelowy = listagraczy.FirstOrDefault(item => item.czyAktywny && item.Id == 3);
Also you can use boolean values directly in conditions (i.e. item.czyAktywny instead of item.czyAktywny == true).
After little refactoring your method should look like
public static Gracz UstawAktywnegoGracza(List<Gracz> listagraczy, int ID)
{
return listagraczy
.FirstOrDefault(item => item.Id == 3 && (ID != 4 || item.czyAktywny));
}
How it works:
You have two conditional blocks in your method if (ID == 4) and if (ID != 4) (which is actually if ... else. Difference is that you are filtering sequence by one more condition in first case - item.czyAktywny should be true. In second case this property does not matter. So, you can add one filtering condition instead (ID != 4 || item.czyAktywny) - czyAktywny will be verified only if ID equal to 4. Also you don't need to create new Gracz object in your method, because you anyway return one from passed list.
Instead of gracz = (Gracz)docelowy;, use gracz = docelowy.FirstOrDefault();
Your select statement is returning an IEnumerable<Gracz>. So, when you attempt to cast it to Gracz directly, the computer doesn't know how to do that and throws the error you're seeing.
There are a number of ways you can handle this situation, but the simplest would be to simply add FirstOrDefault to your invocation, giving you
gracz = docelowy.FirstOrDefault();
instead of what you currently have. By the way, you'll need to add this to your other if statement too - it has the same problem.
Related
String Sex = getSex(); // return M or F
String[] members = getMembers(); // return member codes in array or null
//if members array is null, no filtering for member codes
var query = from tb in MemberTable
where tb.sex.Equals(Sex) &&
(members != null ? members.Contains(tb.membercode) : true)
select tb;
The code doesn't return correct result. It returns all members no matter what members[] is.
Actually the original LINQ is complex so if there are any other possible solutions, I do not want to write the following:
if (members == null){ /*LINQ1*/ }
else { /*LINQ2*/ }
which is not a good coding style.
Any suggestion for solving this problem?
var query = MemberTable.Where(x=>x.sex.Equals(Sex))
if (members != null)
query = query.Where(x=>members.Contains(x.membercode))
//use your query
query.ToList();
OR
var query = from tb in MemberTable
where tb.sex.Equals(Sex) &&
(members == null || members.Contains(tb.membercode))
select tb;
I prefer the first.
Since || short-circuits, you should be able to do this:
var query = from tb in MemberTable
where tb.sex.Equals(Sex) &&
(members == null || members.Contains(tb.membercode))
select tb;
The (members == null || members.Contains(tb.membercode)) subexpression will be true if members is null, so Contains would not be evaluated.
var list = new List<ModelName>();
list = ctx.MemberTable
.Where(c => c.sex==Sex)
.Where(c => c.membercode==true)
.ToList();
I have a search form which i want to use to search a database for data. The searchbox has 4 checkboxes and 1 textfield. The problem is how do i build the linq query considering i dont know beforehand what textboxes the user will check for filtering the search. What i have so far is:
[HttpPost]
public ActionResult search(string ulv, string bjorn, string jerv, string gaupe)
{
var query = (from o in db.observasjonene select o);
if (ulv != null)
{
query = query.Where(o => o.art == ulv);
}
if (bjorn != null)
{
query = query.Where(o => o.art == bjorn);
}
if (jerv != null)
{
query = query.Where(o => o.art == jerv);
}
if (gaupe != null)
{
query = query.Where(o => o.art == gaupe);
}
IEnumerable ls = query.ToList();
return Json(ls, JsonRequestBehavior.AllowGet);
}
The problem with the "where" clause is that if a condition is true, it overwrites the results from the earlier condition. I guess i need an "or" statement or something..
If I have understood your question correctly, you want to check if art equals to any of provided values. You can combine those values into collection and check if collection contains art value:
var values = new [] { ulv, bjorn, jerv, game }.Where(v => v != null);
var query = from o in db.observasjonene
where values.Contains(o.art)
select o;
EF translates Contains into SQL IN operator.
I'm using two approaches in this case:
Build dynamic query:
var q = DB.Invoices.AsQueryable();
if (isPresented != null)
q = q.Where(iv => iv.IsPresented == isPresented);
if (ID != null)
q = q.Where(iv => iv.ID == ID.Value);
...........................
return from iv in q
orderby iv.DueDate descending
select iv;
Use Union to combine search results:
var q1 = db.FeeInvoice.Where(fi => [QUERY1]));
if (isPresented != null)
{
var q2 = db.FeeInvoice.Where(fi =>[QUERY2]));
q1.Union(q2);
}
if (ID != null)
{
var q3 = db.FeeInvoice.Where(fi =>[QUERY3]);
q1.Union(q3);
}
...........................
You are comparing all the parameters value to single column in the query ie. art (see you have written same column name in each where condition) . I'm not sure why are you doing so? you can simply take single parameter which compare the value like this
public ActionResult search(string value)
{
query = query.Where(o => o.art == value);
}
or if it is by mistake and you want to apply where condition along with multiple column then you can try something like this
query=query.Where(o => (o.art == ulv || ulv == string.Empty) && (o => o.bjorn == bjorn || bjorn=string.empty) && (o.jerv == jerv || jerv == string.Empty) && (o.gaupe == gaupe || gaupe == string.Empty));
Note: I assume your column name as your parameters name.
Alright, so I need to get the key value paired differences of two data rows. In short, I'm sending an email to let a user know they've made specific changes to their profile. I already know the rows are different because I'm using the SequenceEqual to determine that.
At the moment I've written and debugged the following code:
if (currentRow.ItemArray.SequenceEqual(updatedRow)) { return; }
var updates = currentRow.ItemArray
.Where((o, i) =>
{
if (o == null && updatedRow[i] == null) { return false; }
else if (o == null && updatedRow[i] != null) { return true; }
else if (o.Equals(updatedRow[i])) { return false; }
return true;
})
.Select((o, i) =>
{
return new AppServices.NotificationData
{
Key = updatedRow.Table.Columns[i].ColumnName,
Value = Convert.ToString(updatedRow[i])
};
}).ToList();
But there are two problems with this code:
It seems really inefficient to me because it's going through each value in the ItemArray and then building a key value pair if the values differ.
It doesn't actually work because the i sent into the Select isn't correct (e.g. if the second column changed, 1, the index sent into the Select is actually 0. Honestly, that makes sense, but I'm not sure exactly how to get what I want here.
CONSTRAINT: I'd like to use LINQ here.
NOTE: I'm only comparing two rows (i.e. it's not going to be going through a list of rows).
What is the appropriate LINQ statement for what I'm trying to do here?
UPDATE: It really feels like I just need to use:
currentRow.ItemArray.Intersect(updatedRow.ItemArray)
but the problem with that is I don't have any idea what field that is so I can't build a key value pair. In other words, I get back only the differences, but I've no clue what the index is so I can't go get a column name based off of those values.
Honestly you're not going to lose much code clarity by using a for loop.
public IEnumerable<AppServices.NotificationData> GetUpdates(DataRow currentRow, DataRow updatedRow)
{
if (currentRow.ItemArray.SequenceEqual(updatedRow)) yield break;
var length = currentRow.ItemArray.Length;
for(var i = 0; i < length; i++)
{
var currentCol = currentRow[i];
var updatedCol = updatedRow[i];
if (currentCol == null && updatedCol == null) continue;
else if (currentCol == null && updatedCol != null) continue;
else if (currentCol.Equals(updatedCol)) continue;
yield return new AppServices.NotificationData
{
Key = updatedRow.Table.Columns[i].ColumnName,
Value = Convert.ToString(updatedCol)
};
}
}
var updates = currentRow.ItemArray
.Select((o, i) => new { Row = o, Index = i })
.Where(r => (r.Row == null && updatedRow[r.Index] != null)
|| (r.Row != null && updatedRow[r.Index] != null
&& !r.Row.Equals(updatedRow[r.Index])))
.Select(r => new
{
Key = updatedRow.Table.Columns[r.Index].ColumnName,
Value = Convert.ToString(updatedRow[r.Index])
}).ToList();
In general, I consider using array index values in LINQ to be a "code smell", and this is a good example of why: the Where clause, in generating a new sequence of values, destroys the illusion that the Select clause is working on the same collection as before.
A quick hack to get around this right now (though I don't think it is quite yet the right solution), would be to swap your Where and Select clauses, essentially:
if (currentRow.ItemArray.SequenceEqual(updatedRow)) { return; }
var updates = currentRow.ItemArray
.Select((o, i) =>
{
if (o == null && updatedRow[i] == null || o.Equals(updatedRow[i])) { return null; }
else return new AppServices.NotificationData
{
Key = updatedRow.Table.Columns[i].ColumnName,
Value = Convert.ToString(updatedRow[i])
};
}).Where(o => o != null).ToList();
I have the following code:
if (intval == 0)
{
var result = (from dm in datacontext.Trk
where dm.ID == 0
select dm);
}
else
{
var result = (from dm in datacontext.Trk
where dm.ID != 0
select dm);
}
if (result != null)
{
// do something
}
There is a swigly line under the result in if (result!= null) saying that the name result does not exist in the current context.
Not sure how to fix this. I tried to initially var result = null but C# didn't like that.
The variable is limited to the block it is declared in. So you have two results, one in if block and one in else block which are different and are not visible outside their blocks.
You need to define the variable out of blocks, but then you need to be specific about the type, because C# compiler needs direct assignment expression to infer the type for var keyword.
However, I suggest rethinking your code and doing somthing like following:
var result = from dm in datacontext.Trk
where ((intval == 0) ? dm.ID == 0 : dm.ID != 0)
select dm;
if (result.Any())
{
// do something
}
Please also note that result will never be null, therefore, I have replaced it with Any but it is not a gist of the question, I believe.
how about something like this:
var result =
intval == 0
?(from dm in datacontext.Trk where dm.ID = 0 select dm)
:(from dm in datacontext.Trk where dm.ID != 0 select dm);
if(results.Any())
{
...
}
You need to declare result before the if statement:
object result = null;
if (intval = 0)
{
result = (from dm in datacontext.Trk
where dm.ID = 0
select dm);
}
else
{
result = (from dm in datacontext.Trk
where dm.ID != 0
select dm);
}
if (result != null)
{
// do something
}
Or you can keep the var declaration in this other variant:
var result = (from dm in datacontext.Trk
where dm.ID != 0
select dm);
if (intval = 0)
{
result = (from dm in datacontext.Trk
where dm.ID = 0
select dm);
}
if (result != null)
{
// do something
}
Now you should somehow find a way to either change that if or remove it completely because result cannot be null at that point.
You can perform the where separately from the main query:
var result = from dm in datacontext.Trk select dm;
if (intval == 0)
{
result = result.Where(dm => dm.ID == 0);
}
else
{
result = result.Where(dm => dm.ID != 0);
}
if (result.Any())
{
// do something
}
You need to declare the result variable before the first if-else.
Also you need paranthesis around the condition in the second if statement.
This code would also cause the problem:
if (value == 0)
{
int result = 1;
}
else
{
string result = "testing";
}
if (result != 1)
{
// do something
}
The first time result is an int, the second time I declare a string, and the third time result is undeclared. The reason that they can have different types is because the first two declarations belong to different scopes. Each { ... } gets its own scope.
If you want to share one variable between scopes, you'll need to declare it outside. But now, since the same variable is used in all three places, there is a compiler error that the types don't match:
int result;
if (value == 0)
{
result = 1;
}
else
{
result = "testing"; // type error here
}
if (result != 1)
{
// do something
}
List<TypeOfDm> dmList; // <=== Declare dmList outside of block statements.
if (intval == 0) { // <=== Use "==" for comparision, "=" is assignement.
dmList = datacontext.Trk
.Where(dm => dm.ID == 0)
.ToList();
} else {
dmList = datacontext.Trk
.Where(dm => dm.ID != 0)
.ToList();
}
if (dmList.Count != 0) {
// do something
}
Note, with your code your result will always be non-null.
[Invoke]
public List<string> GetConCurrentContractId(string identity, string empId, string payMonth)
{
List<string> _rtn = new List<string>();
IQueryable<mContract> query = this.ObjectContext.mContract;
IQueryable<mContract> query2 = this.ObjectContext.mContract.Where(
q => q.wEmpId == empId && q.wEmpId == "NOTVALID");
if (query.Count()>0)
{
_rtn.ToList<string>();
}
return _rtn;
}
query has record return, and query.Count() work,
and query2.count() return exception ...
What is optional way to know any record return?
From your title I'm guessing you get a NullReferenceException. The most likely way I can see this happening only for query2 is if one of the items in mContract is null. To ignore these null objects you can do this:
IQueryable<mContract> query2 = this.ObjectContext.mContract.Where(
q => q != null && q.wEmpId == empId && q.wEmpId == "NOTVALID");
1) Why: because tha autors implemented the method this way.
2) How to solve it: You can create your own extensions method, which accepts null in IEnumerable argument and returns original instance or empty collection (array) for null value:
public static IEnumerable<T> NotNullEnum<T>( this IEnumerable<T> o ) {
if ( object.ReferenceEquals( o, null ) {
return new T[0];
}
else {
return o;
}
}
IQueryable<mContract> query2 = this.ObjectContext.mContract.NotNullEnum().Where(
q => q.wEmpId == empId && q.wEmpId == "NOTVALID");
var count = query2.Count();