Filtering data from Entity Framework - c#

I have simple method where I retrieve data from database and send it to the View. But in the meantime data need to filtered. I have below code:
public ActionResult Index(string Name, string Manufacturer)
{
var dev = db.Devices;
if(!String.IsNullOrEmpty(Name))
{
dev = dev.Where(w => w.Name.Contains(Name));
}
if(!String.IsNullOrEmpty(Manufacturer))
{
dev = dev.Where(w => w.Manufacturer.Contains(Manufacturer));
}
return View(dev.ToList());
}
but I'm getting this error:
Cannot implicitly convert type
'System.Linq.IQueryable' to
'System.Data.Entity.DbSet'. An explicit
conversion exists (are you missing a cast?)
I tried adding cast eg:
(DbSet<Device>)
But didn't helped. Can anyone suggest me how to modify my code?

The problem is db.Devices will be a DbSet<Device> collection, not an IQueryable<T>, so on these lines
dev = dev.Where(...)
the Where will return IQueryable<T> and given DbSet<T> can't be implicitly set as IQueryable<T> you get an exception.
What you need to do here is convert your DbSet<T> to an IQueryable<T> and that can be done pretty easily by calling AsQueryable i.e.
var dev = db.Devices.AsQueryable();

By
var dev = db.Devices;
you declare dev to be of type DbSet<Device>. The Where-methods return an IQueryable and therefore, you cannot use the variable dev. Change the declaration as follows:
var dev = db.Devices.AsQueryable();

Related

return in if statement throws conversion error

I will apologize in advance for the long post. Just trying to give you all the information I have.
I have an if statement in a method that looks like this:
var comparison = await SystemService.SearchCount();
var fileExporter = Configure();
var fileName = "SearchResults"
if (defaultValue <= comparison)
{
var result = SearchResult.Rows.Where(s => VSR.Any(s2 => s2.ID == s.Values.FirstOrDefault()));
var records = SearchResult.Rows.ToList();
await Task.Yield();
return fileExport.ToCsv(records, fileName);
}
The error that I am getting is the following error:
cannot convert from 'System.Collections.Generic.List<SearchRows>' to 'System.Collections.Generic.IList<SearchResults>'
I tried to change the return to explicitly cast to IList like this:
return fileExport.ToCsv((IList<SearchResults>)records, fileName);
This will let it build in Visual Studio but it throws an InvalidCastException when I run it and look at the developer tools:
System.InvalidCastException: Unable to cast object of type 'System.Collections.Generic.List[SearchRow] to type System.Collections.Generic.IList[SearchResult].
What am I missing here? I don't see an issue at all with the code.
The SearchResults model is a listing of the records to be returned (Id, name etc)
The SearchRows model serves as a wrapper for the columns and rows (I didn't name these they came in with the legacy code)
records is of type List<SearchRow>, which is not compatible with the type List<SearchResult>, you either have to convert the SearchRows to SearchResults (e.g. via a Select) or alter the type accepted by ToCSV

EF Core Get DBSet by string then use it on a query

I am trying to make a tool that enables a user to select tables/columns from a ui. When the user posts the "query configuration object" to the server, I want to create a dynamic SQL Query using Entity Framework Core
Example
Given var tableName = "Table1";
I want to grab the DbSet<tableName> and then run something like
var dbSet = GetDbSet("Table1");
var stuff = await dbSet.Take(10).ToListAsync();
I'm sure this is possible in some shape/form but all the articles I'm seeing are similar in the approach. Everything compiles, but when I run it, I get Object Refeerence not set to an instance of an object fun.
Here's what I have:
var select = GetDbSet(tableName);
var results = await select.Take(10).ToListAsync();
The GetDbSet method:
This works obviously But, I need to variablize the T (which I can't do??)
private DbSet<Table1> GetDbSet(string name)
{
return _dbContext.Set<Table1>();
}
From what I've read, I created an extension method since I need Set(T) and not Set<T>()
public static IQueryable<object> Set(this DbContext _context, Type t)
{
return (IQueryable<object>) _context.GetType().GetMethod("Set").MakeGenericMethod(t).Invoke(_context, null);
}
This does what I think I'm expecting it to:
private IQueryable GetDbSet(string name)
{
// forcing a type instead of fiddling with the string for simplicity
return _dbContext.Set(_dbContext.Table1.GetType());
}
But, this code won't compile:
var select = GetDbSet(tableName);
var results = await select.Take(10).ToListAsync();
'IQueryable' does not contain a definition for 'Take' and no
accessible extension method 'Take' accepting a first argument of type
'IQueryable' could be found (are you missing a using directive or an
assembly reference?)
Am I even on the right path for grabbing a DbSet and using it to query? Do I need to build extension methods for Take, and any other methods I want to use?

how to get data from linq database model

I am trying use LINQ in a C# program to get information from a database. I have found a lot of examples showing basic to advanced queries, but i get a error when i try to build. See basic LINQ example below:
The class with the LINQ
public class StdFy
{
public object GetStdFy(DrillholeEntities ddb)
{
try
{
var myList = ((from t1 in ddb.DTM_QAQC_BLK_STD from t2 in ddb.DTM_STANDARDSASSAY.Where(x=> t1.STANDARDID==x.STANDARDID && t1.ASSAYVALUE==x.STANDARDVALUE)
select new
{
CHECKID = t1.CHECKID,
STANDARDID = t1.STANDARDID,
PRIORITY = t1.ASSAY_PRIORITY,
NAME = t1.ASSAYNAME,
ASSAYVALUE = t1.ASSAYVALUE,
STANDARDVALUE = t2.STANDARDVALUE,
STANDARDDEVIATION = t2.STANDARDDEVIATION,
NORMALIZACION = (t2.STANDARDVALUE- t1.ASSAYVALUE)/ t2.STANDARDDEVIATION,
LABJOBNO = t1.LABJOBNO,
LOADDATE = t1.RETURNDATE
})).OrderBy(x => x.LOADDATE).ToList();
return myList;
}
catch (Exception)
{
throw new NotImplementedException();
}
}
}
and then
DrillholeEntities ddb;
StdFy stdFy = new StdFy();
using (ddb = new DrillholeEntities())
{
IOrderedEnumerable<DTM_QAQC_BLK_STD> datosTodos;
datosTodos = stdFy.GetStdFy(ddb);
}
and when i buuild the project i get the error
Severity Code Description Project File Line Suppression State
Error CS0266 Cannot implicitly convert type 'object' to
'System.Linq.IOrderedEnumerable'.
An explicit conversion exists (are you missing a
cast?) Inspinia_MVC5 C:\Users\chachl9\Documents\Visual Studio
2015\Projects\MVC5_Full_Version\Inspinia_MVC5\Controllers\GraphsController.cs 55 Active
You are returning a list of objects of an anonymous type by
select new { ... }
thats may the reason why you use object as return type of your method.
Than you assign the return value to a specific type. Thats the reason why the exception ist thrown.
To get this work I would implement a new class which contains all your needed properties. Use it in
select new MyNewClass { Property1 = ...}
change the return type of your method from object to IEnumerable<MyNewClass>. Aswell the variable you assign the return value to.
You should also use PascalCase properties as mentioned by Gert Arnold in the comments.
Also mixing the select from in where LINQ syntax with the Lambda methods .Where(x => ...) make it hard to read.

Abstracting out queries to the Azure Table Storage using Expressions

I'm creating a class to perform CRUD functionality with Azure Table Storage.
I'm using generic types in this.
I have the following method, which i'm trying to pass in an expression to get used in the TableQuery, but am having some issues.
The line TableQuery<T> query = new TableQuery<T>().Where<T>(criteria); won't compile, and gives me the message
Cannot implicitly convert type 'System.Linq.IQueryable<T>'
to 'Microsoft.WindowsAzure.Storage.Table.TableQuery<T>'.
An explicit conversion exists (are you missing a cast?)
I understand the message and know it's telling me i'm missing a cast, though I'm unsure how to code it correctly.
My full method is:
public List<T> GetSome<T>(Expression<Func<T, bool>> criteria) where T : ITableEntity, new()
{
TableQuery<T> query = new TableQuery<T>().Where<T>(criteria); // <---- This line isn't working
List<T> results = table.ExecuteQuery<T>(query).ToList<T>();
return results;
}
Ok, so I figured it out - how i can pass in a lambda expression for Azure Table Storage to use.
I changed my method to the following:
public List<T> GetSome<T>(Expression<Func<T, bool>> criteria) where T : ITableEntity, new()
{
// table, in this case, is my `CloudTable` instance
List<T> results = table.CreateQuery<T>().Where(criteria).ToList();
return results;
}
I can now pass in an expression. For example, to search against a DynamicTableEntity I can use:
// my table storage class
TableStorage ts = new TableStorage("ContactData");
// search with expression
List<DynamicTableEntity> results = ts.GetSome<DynamicTableEntity>(t => t.Properties["FirstName"].StringValue == "Darren");
If this is something you wouldn't/shouldn't do against an Azure Table Store, please do let me know.
In the meantime, this is how I have met the requirement.
The error is because the value returned by the extension method Where is of type IQueryable<T>, but you're assigning to a variable of type TableQuery<T> and there is no implicitly valid type conversion between these types.

Linq Retrieve Entities using a Navigational Property

Linq and EF.
I'm pretty new so I have some problem to retrieve entities using a Navigational Property (CmsContents).
I can return as an List but not as an IEnumerable.
Could you tell me what is wrong in my code?
Also do you know a better approach to retrieve Entities suing Navigational Properties?
Please provide me an example of code thanks!
public IEnumerable<CmsGroupsType> GetMostPopularContents()
{
using (var context = new CmsConnectionStringEntityDataModel())
{
context.CmsGroupsTypes.MergeOption = MergeOption.NoTracking;
var contents = context.CmsGroupsTypes.Single(g => g.GroupTypeId == 1).CmsContents;
return contents.ToList();
}
}
Error 1 Cannot implicitly convert type 'System.Collections.Generic.List<WebProject.DataAccess.DatabaseModels.CmsContent>' to 'System.Collections.Generic.IEnumerable<WebProject.DataAccess.DatabaseModels.CmsGroupsType>'. An explicit conversion exists (are you missing a cast?)
The generic types don't match: Your .ToList() is of CmsContent, but your return type is an IEnumerable of CmsGroupsType. I'm not sure if that was intentional, but changing the return type to IEnumerable<CmsContent> will make everything work.
Change your return type from CmsGroupsType to WebProject.DataAccess.DatabaseModels.CmsContent

Categories

Resources