I am using a variable var for getting the result from my database and I want to compare it with my enum value to do some processes. But I am facing the problem var cant compare with the enum value.I have tried to convert both of the variable to String but still cant make it. Any idea of doing so?
//Fetch the value from database
var resultActivateQR = from value in db.QrCodes
where value.Code == qrCode
select value.Status;
//Want to compare the value
if (resultActivateQR.Equals((int)Status.New))
{
return true;
}
else
{
return false;
}
//My Enum In other class
public enum Status
{
New = 0,
Activated = 1,
Void = 2,
}
Your variable resultActivateQR would be an IEnumerable collection object returned from your LINQ statement. You would need to use a LINQ method like .Single() or .First() to get the Status of the one record that matched your qrCode (assuming there should always just be one record return from the database from the LINQ statement).
So your code could look something like this (this is more concise but essentially does what it seems like you needed):
var resultActivateQR = db.QrCodes.Where(x => x.Code == qrCode).Single();
//Want to compare the value
return resultActivateQR.Status == (int)Status.New;
This will bring back the single object the represents the database record that matches your QR Code and then compares that objects status to your enum Status.New and will return true or false from the comparison.
Writing a LINQ query, as you did, creates just queryable object, which does not contain any data, just query itself. It is called deferred exectuion, meaning that data is fetched when it is needed.
So one way is to call method such as ToList() or ToArray().
From your question I guess you expect one record to be fetched or you want to get one record, which requires calling First() method or FirstOrDefault(), which would also materialise data.
Second matter is the type of Value column, but I guess it's an int, so you can easily compare with your enum. Otherwise, you should cast your enum to appropriate datatype in order to successfully compare it with value in column.
Related
I have a value I'm getting dynamically. This is because it exists in an abstraction method I'm using to build a query from a dot-notation representation of deeply related property.
I need to know if the value contains a particular value. This is easy enough for a string, but when the object in question is a collection I can't figure how to check. I can assume it's a List in my situation, but I don't know what type of list, so I can't achieve a property casting with something like List<int>.
So where x is an object and spec is dynamic this is how I test for string:
return x.ToString()?.Contains(spec, StringComparison.InvariantCultureIgnoreCase) ?? false;
This successfully determines if it's a collection type, but I still can't call Contains on it:
if (x.GetType().Namespace == "System.Collections.Generic")
{
return x.Contains(spec); //does not work
}
Also tried:
var list = (List<dynamic>)x;
var list = (List<object>)x;
But this fails in my test scenario with List<int>
So currently, you can imagine I have 1 method that is the constructor that funcitons like
info.PersonalInfo=getPersonalInfo(Id);
info.MedicalInfo=getMedicalInfo(Id);
Thing is, all of those get data and get binarys are repeating 95% of the code
using (CVDataEntities data = new CVDataEntities())
{
var temp = data.PersonalInfo.Where(m => m.Id == Id).FirstOrDefault();
return temp;
}
The only thing that changes is instead of PersonalInfo its MedicalInfo.
I thought of using a switch and just sending a number as the selector for which specific object I would want.
But the problem is the method is made so that it can only return
public IEnumerable<PersonalInfo> getPersonalInfo (string Id)
Is there any way for me to make a IEnumerable that lets me return any object, or is there a better way to go about this. I want to do it mostly to reduce the code from 400 lines down to 200 at most.
Try using generic methods, you will be able to specify the return type of your function when you call it. This could make your code look like this :
public IEnumerable<T> getInfo<T>(string id)
{
// Some code
}
// Calling the function
info.PersonalInfo = getInfo<PersonalInfo>(Id);
info.MedicalInfo = getInfo<MedicalInfo>(Id);
But be careful while using it, cause the compiler won't know what type T is (it is only defined at runtime) so it could lead to some errors while processing the data (like missing properties / methods exclusive to a specific type)
EDIT : Johnathan Barclay made a good point by commenting that the // some code bit is relevant and asked "How would the correct property be selected on data? How do you access an Id property on T?"
To get the correct property and access an Id property, you could use System.Reflection and add a string parameter to get the name of the property you want to use, and another to give the Id property name to the function:
public IEnumerable<T> getInfo<T>(string id, string propertyToReadName, string propertyToCompareName)
{
using (CVDataEntities data = new CVDataEntities())
{
// Getting the enumerable not filtered first
IEnumerable<T> unfilteredList = (IEnumerable<T>)data.GetType() // Get the type
.GetProperty(propertyToReadName, typeof(T)) // Get the property (PersonalInfo or MedicalInfo)
.GetValue(data); // Get the value of this property in the `data` instance
// Filtering the list
IEnumerable<T> filteredList = unfilteredList.Where(m =>
typeof(T).GetProperty(propertyToCompareName) // Get the "id" property using parameter
.GetValue(m) // Get the "id" value of m instance
.Equals(id)); // Check if it equals the id given as parameter
return filteredList;
}
}
// Calling the function
info.PersonalInfo = getInfo<PersonalInfo>(Id, "PersonalInfo", "Id");
info.MedicalInfo = getInfo<MedicalInfo>(Id, "MedicalInfo", "Id");
If you want to return a single element instead of an IEnumerable don't forget to change the return type of the function from IEnumerable<T> to T and add .FirstOrDefault() at the return line
Note that you could also give another value to the parameter propertyToCompareName and make a comparison to another property of the T class
This code snippet returns me an error,
public List<auto> autoSelect()
{
return autoSelect(DateTime.Today);
}
public List<auto> autoSelect(DateTime date)
{
var onderhoudAuto = (from onderhoud in db.onderhouds
where onderhoud.uitvoerdatum != DateTime.Today
select onderhoud)
.FirstOrDefault();
List<string> autos = (from auto in db.autos
where auto.autoId.Equals(onderhoudAuto)
select auto)
.FirstOrDefault();
return autos;
}
I tried convert the var to a list with .ToList(); although this doesn't work. Does anyone have any suggestions?
I tried convert the var to a list
No, you do not. var is not actually a data type - it is resolved by the compiler. A tooltip should show you the real type.
Your problem is different:
Looking at your code, we can see:
The method autoSelect signature states that the return type is List<auto>
public List<auto> autoSelect(DateTime date)
The variable autos type is List<string>
List<string> autos = [...etc...]
return autos;
You return autos, but it is not possible to return a List<string> when a List<auto> is expected.
So it has nothing to do with var - it is simply you selecting as single property and returning a list of strings, but that is not the type the method is supposed to return.
If you use FirstOrDefault() after your linq query, you are saying you want the first element (or the default -usually null- for the datatype if none matches) in the LINQ query, not a list of elements.
If you want a list of elements, use ToList() on the linq query, not try to convert a single entity to a list.
If you, for some reason, want a list of a single entity, then create a list (with new List<type>()) and then add your entity (of the same type as your list) to the list.
I am trying to do something like a SQL 'in', which I understand to be more or less equivalent to 'contains' in LINQ.
This is the query I've come up with after reading through several other similar questions and this...
http://blogs.msdn.com/b/alexj/archive/2009/03/26/tip-8-writing-where-in-style-queries-using-linq-to-entities.aspx
public ActionResult recentbookings(string recent_bookings)
{
List<booking> bookings = db.bookings.Where(s => recent_bookings.Contains("36525")).ToList();
return PartialView("_recentbookings", bookings);
}
This query returns every record in the table.
I want and expect the query to return one record matching the id I'm passing in.
The 'recent_bookings' value is coming from localstorage through a javascript call...
var url = '#Url.Action("recentbookings", "booking")';
url += "?recent_bookings="+ localStorage['recent_bookings'];
$("#ajaxresult").load(url);
There happens to be only one item in local storage, which is '36525', which matches the hardcoded 'Contains("36525")' in my query.
I believe there's a simple problem with my query logic as I don't really understand it, compared with the SQL in.
Once I get this sorted out, I'll go on to parsing out multiple values from the incoming string.
public ActionResult recentbookings(string recent_bookings)
{
var recent_bookings_array = new[] { int.Parse(recent_bookings) };
booking[] bookings = db.bookings.Where(s =>
recent_bookings_array.Contains(s.Id)).ToArray();
return PartialView("_recentbookings", bookings);
}
You were using .Contains incorrectly. You are right, it is like an IN clause, but the object you invoke .Contains on should be like the IN (36525) part of your SQL query. The above query is basically saying "Give me all of the bookings where the booking ID is in this array of recent booking id's."
Why is your result returning all booking records?
...because the Where clause argument is a Func<T, bool>. Meaning, the result of the lambda expression must be either true or false. The expression in your question, s => recent_bookings.Contains("36525") will always return true, since the string "36525" is contained within your recent_bookings variable. Since it is always true, all of your rows get returned. You never checked anything against your data, only your local variables.
On another note, don't call .ToList on your result unless you need to add / remove items to / from it before returning the view. .ToArray is much faster, but returns an immutable collection.
I have a table named InventoryItem which consists of columns ItemDescription and Item BalanceQty.I want to fetch the BalanceQty of the ItemName selected in a comboBox.For this,I created a method in my Data Access Layer And passed the string parameter representing the string value of ItemDescription to this method.This has been implemented using Entity Framework.This is how my code looks:
public float GetAvailableQty(string itemName)
{
float availableQty =(from table in context.InventoryItem
where table.ItemDescription == itemName
select table.BalanceQuantity);
return availableQty;
}
But it is giving me the following error-
Cannot convert type 'System.Linq.IQueryable' to 'float'
Where am I going wrong?
Probably you need this:
double availableQty =(from table in context.InventoryItem
where table.ItemDescription == itemName
select table.BalanceQuantity).Sum();
IQueriable returns an expression tree. The result of query like this is a rows set, and it can be materialized to IEnumerate by using of ToList() or implicitly by assigning to IEnumerable. But anyway it will be rows set, not a single value. If you sure the query returns the single one then use .Single() or SingleOrDefault. See other extension methods for IQueriable.
Otherwise, if you need an array then assign result to some IEnumerable variable.
Because your Linq returns an Iqueryable ...
Lets assume you have 3 rows with with an item with 3 different quatities (silly, i know, but think about other things that can have multiple values per item, like colors for a paint). Your linq will return the three quantities, and you're assuming it's a number
You could use First or FirstOrDefault to fetch the first item, or the default value for that object.
In your case, it shouldn't matter, but you should realize how Linq works and what it returns ...
Another example:
let's assume : List numbers = {1,2,3,4,5,6} (let's assume they are ints).
and you do : var small_numbers = numbers.Where(x => x<4)
What you get is something you can then query like: foreach (var small in small_numbers) {...}). The result is not an int.
You could take the first, last, and indeed, that would be an int. But what you get is a collection. so, even if you do: var one_result = numbers.Where(x => x<2), one_result is not an int.