How to verify results returned by EF Core query using debugger in Visual Studio 2015 - entity-framework

In an ASP.NET MVC Core Web project, without using any third party tools (LINQPad etc.) how can we achieve the above for a LINQ query such as the one shown in an Action Method below.
NOTE:
I'm using EF Core and VS2015
Project is MVC Code First
Action Method:
public async Task<IActionResult> PostBlogs(string returnUrl = null)
{
var qry = from a in _context.Blogs
where a.Url.Contains("Contoso")
return View(await qry.ToListAsync());
}

To see the query result where you have to construct your method as shown below.
public async Task<IActionResult> PostBlogs(string returnUrl = null)
{
var qry = from a in _context.Blogs
where a.Url.Contains("Contoso");
qry = await qry.ToListAsync();//you can see the result here when you expand it
return View(qry);
}
You have to configure like this to see the SQL : Logging

Related

How do I filter a result set in Entity Framework Core?

I have a dinky little web service written in Entity Framework Core that returns a list of coils that have been, are being or will be annealed. I don't care about the ones that have been annealed. How do I put filter out the finished ones?
The Inventory table includes a column archived. I want to query for those rows for which the archived column contains zero. How do I do that?
The query is being performed in an extension method on the IEndpointRouteBuilder interface:
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using System.Collections.Generic;
using System.Text.Json;
using CAPSWebServer.CapsDataModels;
namespace Microsoft.AspNetCore.Builder
{
public static class CAPSServiceEndpoint
{
public static void MapWebService(this IEndpointRouteBuilder app)
{
app.MapGet("caps/coils", async context =>
{
CapsDataContext data = context.RequestServices.GetService<CapsDataContext>();
var coils = data.Inventories;
context.Response.ContentType = "application/json";
await context.Response.WriteAsync(JsonSerializer.Serialize<IEnumerable<Inventory>>(data.Inventories));
});
}
}
}
Assuming archived is a bool, you should be able to do:
await data.Inventories.Where(inventory => !inventory.Archived).ToListAsync();.
You'll most likely need a using for System.Linq and Microsoft.EntityFrameworkCore

OData v4 post-processing of results (works with v3, not with v4)

I have a Web API server (with EF 6.x) and I need to do some post-processing of the result set from OData queries in the controller. On the client-side I use a DevEx grid and their ODataInstantFeedbackSource.
With no post-processing, everything works fine, e.g.:
http://somesite.us/odata/Items/$count
[EnableQuery]
public IHttpActionResult GetItems(ODataQueryOptions<Item> queryOptions)
{
return Ok(Context.Items);
}
It does not work with post-processing (same simple $count query, but without EnableQuery since I am manually applying the query options):
GET http://somesite.us/odata/Items/$count
//[EnableQuery]
public IHttpActionResult GetItems(ODataQueryOptions<Item> queryOptions)
{
queryOptions.Validate(_validationSettings);
var query = queryOptions.ApplyTo(Context.Items, new ODataQuerySettings()) as IQueryable<Item>;
var resultList = new List<Item>();
foreach (var item in query)
{
item.OrdStat = "asf"; // Some post-processing
resultList.Add(item);
}
return Ok(resultList.AsQueryable());
}
This throws an exception:
Microsoft.OData.ODataException
HResult=0x80131509
Message=The value of type 'System.Linq.EnumerableQuery`1[[SomeService.Model.Item, SomeService.Model, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]' could not be converted to a raw string.
Source=Microsoft.OData.Core
StackTrace:
at Microsoft.OData.RawValueWriter.WriteRawValue(Object value)
Note: with ODATA v3, the above works just fine. It is only with v4 that I get an exception when not using [EnableQuery].
If I add back the [EnableQuery] attribute, this simple $count query works with ODATA v4, but with more complex queries, the data returned to the client gets messed up (likely due to $skip, etc. being applied both by me and by the EnableQuery attribute).
For example, this query generated by the DevEx grid when you scroll down:
http://somesite.us/odata/Items?$orderby=ItemNo&$skip=300&$top=201
Results in (client-side): Unexpected number of returned keys: 0. Expected: 201
I assume that I need to remove the EnableQuery attribute since I am manually applying the query options, but why am I getting the "could not be converted to a raw string" exception when I do this?
How can I properly implement post-processing in this scenario?
I opened a support request with Microsoft on this, and they eventually determined that it is a bug in ODATA v4 and they created this bug report:
https://github.com/OData/WebApi/issues/1586
The workaround is to check if the query is a count query and, if so, return Ok(query.Count());
if (queryOptions.Context.Path?.Segments.LastOrDefault() is CountSegment)
return Ok(query?.Count());
Here is a more complete sample snippet / POC which works fine with ODATA v4:
private static ODataValidationSettings _validationSettings = new ODataValidationSettings();
[ODataRoute("Customers")]
public IHttpActionResult Get(ODataQueryOptions<CustomerLookup> queryOptions)
{
queryOptions.Validate(_validationSettings);
var query = queryOptions.ApplyTo(Context.CustomerLookup) as IQueryable<CustomerLookup>;
if (queryOptions.Context.Path?.Segments.LastOrDefault() is CountSegment)
return Ok(query?.Count());
var resultList = new List<CustomerLookup>();
foreach (var customer in query)
{
customer.Address = "1234_" + customer.Address;
resultList.Add(customer);
}
return Ok(resultList.AsQueryable());
}

pagedlist performance impacts using c# asp mvc

i included .NET XPAGED LIST in my project using nuget and is successfully working
the code is
public ActionResult Index(int? page)
{
var query = from p in db.Posts orderby p.ID ascending select p;
Console.WriteLine(query);
var pageNumber = page ?? 1;
ViewData["Posts"] = query.ToPagedList(pageNumber, 10);
return View();
}
the main question is that we are using the query to extract all records. then those are skipped and taken by
.ToPagedList(pageNumber,elementsperpage);
but this creates performance issues.
The query must extract only paged/limited elements like LIMIT(0,5)
do pagedlist limits or i have to create my custom function for paging in asp mvc

Create async methods to load data from database using EF

how does one write an async method that gets data from database, using DbContext and .NET 4.0?
public Task<List<Product>> GetProductsAsync()
{
// Context.Set<Product>().ToList();
}
so we can await somewhere for result of this method
// somewhere
List<Product> products = await repository.GetProductsAsync();
What is important is that I do not want to use thread pool thread for this task, since this is an IO task, and I need to support framework 4.0, and EF6 had added support for async methods only in 4.5, if I am not mistaken.
Not possible, SaveAsync is wrapped with:
#if !NET40
Source: https://github.com/aspnet/EntityFramework6/blob/master/src/EntityFramework/DbContext.cs#L335
Installing Entity Framework 6 is available as a Nuget Package and works also with .NET 4. In EF6, async
DB calls can be done like this example:
public static async Task<List<Customer>> SelectAllAsync()
{
using (var context = new NorthWindEntities())
{
var query = from c in context.Customers
orderby c.CustomerID ascending
select c;
return await query.ToListAsync();
}
}
Here, a DbContext is instantiated in a using block and the query will search the Northwind database for all its customers and order ascending by primary key CustomerID. The method needs to be decorated with async keyword and must return a task of the desired type T, here a list of customers. The result will then be return by using the ToListAsync() method in this case and one must remember to use the await keyword. There are additional Async methods in EF6, such as SaveChangesAsync, SingleOrDefaultAsync and so on. Also, async methods in C# should following this naming conventions according to guidelines.
To get started test the code above in Visual Studio, just create a new Console Application solution, type: install-package EntityFramework in the Package Manager Console and add an edmx file pointing to a local Northwind database. The main method will then just call the method above like this:
class Program
{
static void Main(string[] args)
{
Stopwatch sw = Stopwatch.StartNew();
var task = CustomHelper.SelectAllAsync();
task.Wait();
Console.WriteLine("Got data!");
List<Customer> data = task.Result;
Console.WriteLine(data.Count);
Console.WriteLine("Async op took: " + sw.ElapsedMilliseconds);
sw.Stop();
sw.Start();
//data =
//var data = CustomHelper.SelectAll();
//Console.WriteLine("Got data!");
//Console.WriteLine(data.Count);
//Console.WriteLine("Sync operation took: " + sw.ElapsedMilliseconds);
Console.WriteLine("Press any key to continue ...");
Console.ReadKey();
}
}
I see that the async operation takes a bit longer than the sync operation, so the async db call will have some time penalty but allows asynchronous processing, not freezing the calling code awaiting the result in a blocking fashion.

Will calling a nested Navigation Property retrieve all the parent navigation properties?

I am using Entity Framework inside an asp.net mvc web application. I have the following query:-
public AccountDefinition GetCustomer2(int id){
var c = entities.AccountDefinitions.Where(s=>s.ORG_ID==id)
.Include(a=>a.SDOrganization)
.Include(a1=>a1.SiteDefinitions);
var c2 = c.Select(a=>a.SDOrganization); //code goes here }
Which is called from the following Action Method:-
public ActionResult Index(int searchTerm)
{ var accountdefinition = repository.GetCustomer2(searchTerm).ToList();
return View(accountdefinition);
}
So when I am creating the c2 var will it query the database or the data will be inside the memory from the first call, when reaching the .Tolist()?.
Second question if I replace the .Include with .Select when creating the Var c, will it have the same effect?
You can see what query is executed in the SQL Server Profiler (if using SQL Server), or you can have a look at some Entity Framework Tracing Provider. http://code.msdn.microsoft.com/EFProviderWrappers-c0b88f32
This will give you lots of information and understanding...