.NET Core - EntityFrameworkCore - Unable to cast object of type 'Query.Internal.EntityQueryable` to type 'DbSet` - asp.net-core

I try to implement a search with entity when a search field is provided
but I get a weird casting error I just dont understand
Unable to cast object of type 'Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable`1[SomeApp.Models.Partner]' to type 'Microsoft.EntityFrameworkCore.DbSet`1[SomeApp.Models.Partner]'.
here is the code of my controller entry point
I tried forcing the cast, but apparently there is something wrong with my code
[HttpPost]
public async Task<ActionResult<PartnersFetch>> GetPartners(PartnersSearch partnersSearch)
{
DbSet<Partner> data = _context.Partners;
if (partnersSearch.SearchById != null)
{
// the following line causes problems :
data = (DbSet <Partner>) data.Where( p => p.Id == partnersSearch.SearchById.GetValueOrDefault());
}
thanks for helping me on this

I forgot to use AsQueryable
var data = _context.Partners.AsQueryable();
if (partnersSearch.SearchById != null)
{
data = data.Where( p => p.Id == partnersSearch.SearchById.GetValueOrDefault());
}

data.Where(...) will return an IQueryable which you can materialize as follows
List<Partner> myResult = data.Where(...).ToList();
The DbSet<Partner> is only the set on which you can query data. Your goal very likely is to get the partners out of it, right?

Related

Why is this attempt at getting length property on array failing in AS3?

I'm getting data from an SQL database.
var result: SQLResult = sqlStatement.getResult();
var resultsArray:Array;
if (result != null)
{
resultsArray = result.data;
trace(resultsArray.length);
}
When there's data in the database, the above code works fine. When there's not data, it errors out on the trace line...
Error #1009: Cannot access a property or method of a null object reference.
Why is that? Why is it making it through the conditional when result is null?
Thank you.

LINQ Does not contain a definition for 'union'

what is wrong with this linq query that show me the error of Does not contain a definition for 'union'
(from rev in db.vM29s
where Years.Contains(rev.FinancialYear) && rev.Exclude=="No"
group rev by new { rev.RevenueCode, rev.FinancialYear } into g
select new
{
Revenuecode = g.Key.RevenueCode,
totalRevenue = g.Sum(x => x.RevenueAmount),
RevenueEnglish = (from a in db.RevenueCodes where a._RevenueCode == g.Key.RevenueCode select a.RevenueEng).FirstOrDefault(),
// MinorCode = (from a in db.MinorCodes where a._MinorCode == g.Key.MinorCode select a.MinorEng),
RevenueDari = (from a in db.RevenueCodes where a._RevenueCode == g.Key.RevenueCode select a.RevenueDari).FirstOrDefault(),
Yearss = g.Key.FinancialYear
}
)
.Union
(from u in db.rtastable
where Years.Contains(u.Year)
group u by new { u.objectcode, u.Year } into g
select new
{
Revenuecode = g.Key.objectcode,
totalRevenue = g.Sum(x => x.amount),
RevenueEnglish = (from a in db.RevenueCodes where a._RevenueCode == g.Key.objectcode select a.RevenueEng).FirstOrDefault(),
// MinorCode = (from a in db.MinorCodes where a._MinorCode == g.Key.MinorCode select a.MinorEng),
RevenueDari = (from a in db.RevenueCodes where a._RevenueCode == g.Key.objectcode select a.RevenueDari).FirstOrDefault(),
Yearss = g.Key.Year
}
)
.ToList();
If you included using System.Linq; and both Anonymous Types have exactly the same property names + property types, then what you did should work.
Yet it does not work. The solution is to check your Anonymous Types for subtle property name differences and/or subtle property type differences.
E.g. even an int vs a smallint or double or decimal will cause this build error:
'System.Collections.Generic.IEnumerable<AnonymousType#1>' does not contain a definition for 'Union' and the best extension method overload 'System.Linq.Queryable.Union(System.Linq.IQueryable, System.Collections.Generic.IEnumerable)' has some invalid arguments
Switching to .Concat() will not fix this: it has the same (obvious) restriction that the types on both sides must be compatible.
After you fix the naming or typing problem, I would recommend that you consider switching to .Concat(). The reason: .Union() will call .Equals() on all objects to eliminate duplicates, but that is pointless because no two Anonymous Objects that were created independently will ever be the same object (even if their contents would be the same).
If it was your specific intention to eliminate duplicates, then you need to create a class that holds your data and that implements .Equals() in a way that makes sense.
You should use Concat or using addRange if the data is allready in memory.

SQL Select on MVC4 Controller

I am trying to perform a SELECT on the M1lhao table of Sorteio entity (database).
I don't want to go the traditional "string query" or AddWithParameter() way, i wanted to use the MVC4 EF5 available methods.
The following code passes the entire Table to the View, that i can do a foreach in the View and all works fine. What i am looking for is how can i do a SQL query, so i can pass only the element(s) i want, sorted DESCending (for example), obviously on a List and obeying the Model that the View expects.
Essentially i want a replacement for (i tried variants too, db.Milhao, etc):
var data = db.Database.ExecuteSqlCommand("SELECT * From M1lhao WHERE DrawID = {0}", id);
The problem with Find() is that it only searches primary keys.
The complete code:
public class M1lhaoController : Controller
{
private Sorteio db = new Sorteio();
public ActionResult Index(int id = 1)
{
var data = db.Database.ExecuteSqlCommand("SELECT * From M1lhao WHERE DrawID = {0}", id); // the variable data comes as -1
M1lhao m1lhao = db.M1lhao.Find(id);
if (m1lhao == null)
{
return HttpNotFound();
}
return View(db.M1lhao.ToList());
}
}
Thank you.
You can try as shown below.
var data = db.M1lhao.Where(m=>m.DrawID == id).Select(p=>p);
You can learn more about Method-Based Query Syntax : Projection

asp.net mvc Type.GetMethod when two action with same name, but get and post

in asp.net mvc 4, I write a custom Exception handler, working as a Attribute named HandleCustomError.
In this handler, I should know which action the current request for, then I can know what kind of return type for this action. I will return different data for "return type view() and json".
But, now I have two action with the same name, but one is for "Get", other is for "Post".The method "GetMethod" return an error: " System.Reflection.AmbiguousMatchException "
public class HandleCustomError : System.Web.Mvc.HandleErrorAttribute
{
public override void OnException(System.Web.Mvc.ExceptionContext filterContext)
{
//base.OnException(filterContext);
if (filterContext.ExceptionHandled)
{
return;
}
else
{
//Determine the return type of the action
string actionName = filterContext.RouteData.Values["action"].ToString();
Type controllerType = filterContext.Controller.GetType();
var method = controllerType.GetMethod(actionName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
var returnType = method.ReturnType;
}
....(Omitted)
I also came across this issue that below line was giving Ambigeous issue
controllerType.GetMethod(actionName, BindingFlags.IgnoreCase |
BindingFlags.Public | BindingFlags.Instance);
Reason was that controller has two method with same name one is
[HTTPGET]
and other iis
[HTTPPOST]
.
For to get exact method I use GetMethods and LINQ.
Note: In controller writting [HTTPGet]**on action is not compulsory for get method i.e. on action if HTTpGet is not written the by default .net will consider it as **[HttpGet]. But for post action it is compulsory.
Will use this property for finding the correct method.
Steps
1. Find Type of request
2. Find the action using reflection
Finding Request type:
var actionName =
filterContext.RouteData.Values["action"].ToString();
Type typeOfRequest = filterContext.HttpContext.Request.RequestType.ToLower()
=="get"?typeof(HttpGetAttribute):typeof(HttpPostAttribute);
Finding method:
var cntMethods = controllerType.GetMethods()
.Where(m =>
m.Name == actionName &&
( ( typeOfRequest == typeof(HttpPostAttribute) &&
m.CustomAttributes.Where(a => a.AttributeType == typeOfRequest).Count()>0
)
||
( typeOfRequest == typeof(HttpGetAttribute) &&
m.CustomAttributes.Where(a => a.AttributeType == typeof(HttpPostAttribute)).Count() == 0
)
)
);
MethodInfo actionMethodInfo = actionMethodInfo = cntMethods != null && cntMethods.Count() == 1 ? cntMethods.ElementAt(0):null;
Reference : https://techatfingers.wordpress.com/2016/06/14/session-state-on-action/
As you have mentioned that you have two action with the same name, but one is for "Get", other is for "Post" , You could try out the [HttpGet] to the first action and [HttpPost] to the section action or you can try something like this if your action serves requests from multiple verbs
[HttpGet, HttpPost] or [AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
For Example ,
if your function name is GetMethod then try like this
[HttpGet]
Public ActionResult GetMethod()
{
//do something ...
}
[HttpPost]
Public ActionResult GetMethod()
{
//do something ...
}
One approach to solve this issue is to use the GetMethods() method on the System.Type object to return a list of methods on the System.Type object. Use a LINQ query to filter the method list to just those methods that match a specific action name.
Add this approach by replacing the following in your code:
var method = controllerType.GetMethod(actionName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
with the following if condition that checks if multiple methods are found that match the variable actionName from your code. Define a string variable that identifies the action type (i.e. "HttpGet" or "HttpPost") and compare it to the attributes of each method in the filtered list.
System.Reflection.MethodInfo[] matchedMethods = controllerType.GetMethods(
System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public)
.Where(m => m.Name == actionName).ToArray<System.Reflection.MethodInfo>();
if (matchedMethods.Length > 1)
{
string attributeTypeString = "HttpGet"; // Change this to "HttpPut" or the text of any custom attribute filter
foreach (System.Reflection.MethodInfo methodInfo in matchedMethods)
{
if (methodInfo.CustomAttributes.Count() == 0) { continue; }
// An alternative below is to explicitly check against a defined attribute type (e.g. `ca.AttributeType == ...`).
if (methodInfo.CustomAttributes.FirstOrDefault(ca => ca.ToString().IndexOf(attributeTypeString) == 0) !=null)
{
method = methodInfo;
break; // Break out of the 'foreach' loop since a match was found
}
}
}
else
{
method = controllerType.GetMethod(actionName, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
}
Code notes
I used strongly-typed variable declarations (versus 'var') so it's easier to follow what the code is doing.
Add using System.Reflection; and using System.Linq at the top of the class file. I listed the full assembly declaration of a variable/type/flag in the code above so that again it's easier to follow (at least for me) in this answer.
The first line of code in the above solution can be broken into separate lines to make it easier to follow:
System.Reflection.MethodInfo[] allMethods = controllerType.GetMethods(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
System.Reflection.MethodInfo[] matchedMethods = allMethods.Where(m => m.Name == actionName).ToArray<System.Reflection.MethodInfo>();
Note the if condition within the foreach loop.
if (methodInfo.CustomAttributes.FirstOrDefault(ca => ca.ToString().IndexOf(attributeTypeString) == 0) !=null)
The if condition doesn't have to convert the custom attribute to a string. An alternative is to explicitly check against a defined attribute type (e.g. ca.AttributeType == ...). If the condition does check against the text of an attribute name then ensure the string comparison method (e.g. IndexOf() used here) satisfies the conditions of your application. For example, I used IndexOf() > -1 to determine if the text of variable attributeTypeString is listed anywhere in a custom attribute because I assumed that there should not be another custom attribute that contains the text 'HttpGet'.

How to access columns from an IQueryable when dynamically constructed?

I am using the System.Linq.Data library provided here - http://weblogs.asp.net/scottgu/archive/2008/01/07/dynamic-linq-part-1-using-the-linq-dynamic-query-library.aspx
I have the following query which works great and returns an Iqueryable
IQueryable customer =
ctx.Customers.Where(cust => true).Select("new("Name,Address")");
However, how do I access these returned columns? I cannot access them using a lambda expression as follows:
var test = customer.Where(cust=>cust.Name == "Mike").First();
"cust.Name" in the above case cannot be resolved. It does not exist in the list of methods/properties for "cust".
Am i assuming something wrong here. I understand that I am working with an anonymous type. Do I have to create a DTO in this case?
For any IQueryable you have property called ElementType.
You can use it to get the properties as explained below
IQueryable query = from t in db.Cities
selec new
{
Id = t.Id,
CityName = t.Name
};
if(query!=null)
{
Type elementType = query.ElementType;
foreach(PropertyInfo pi in elementType.GetProperties())
{
}
}
Try foreach loop:
var a = _context.SENDERS.Select(x=>new { Address=x.ADDRESS, Company=x.COMPANY });
foreach(var obj in a)
{
Console.WriteLine(obj.Address);
Console.WriteLine(obj.Company);
}