EF 4.1 Code First Raw SQL - entity-framework

I would like to return entities using RAW SQL, so I have the following code which returns a set of Entities:
var rawSql = "exec spFindStories #pattern, #page, #pageSize";
// use raw SQL because SP is needed
// results are not tracked.
var stories = context.Database.SqlQuery<Story>(rawSql,
new SqlParameter("#pattern", pattern),
new SqlParameter("#page", page),
new SqlParameter("#pageSize", pageSize)
).ToList();
Now for each one of these stories, I need to load their related Tags. It seems that CF does not load related entities returned in the results. How can I achieve this ??
Thanks!!

Why not add it as a function import and specify what it's returning as the entity you expect?

Related

How to user "merge" in entity framework code first to merge the multiple result set from a stored procedure into one single collection

I am new to entity framework. I have a simple stored procedure that returns 2 result set.
I am using a code-first approach and need to merge the 2 result set into one single collection using "merge". I don't want to modify my stored procedure.
Any help would be appreciated. Thank you.
Just follow the doc here:
Entity Framework Sprocs with Multiple Result Sets
Except in your case both DataReaders load the same entity.
eg
var foos1= ((IObjectContextAdapter)db)
.ObjectContext
.Translate<Foo>(reader, "Foos", MergeOption.AppendOnly);
// Move to second result set and read next set of entities
reader.NextResult();
var foos2 = ((IObjectContextAdapter)db)
.ObjectContext
.Translate<Foo>(reader, "Foos", MergeOption.AppendOnly);
var foos = foos1.Union(foos2).ToList();

Retrieving some columns from database with Breeze.js, and still be able to update database

I am new to Breeze.js, but really enjoy it so far. I ran into an issue with updating a database with Breeze.js, when selecting only portion of columns of a model.
When I ran this statement:
$scope.emFac.entityQuery.from('Company');
the company entity matches my EF entity, retrieves all columns, creates entityAspect, and all is working fine when updating database:
However, when I retrieve only portion of corresponding Model's columns, Breeze.js returns anonymous object with specified properties (retrieving data works, but not updating does not), without the entityAspect, which is being used for tracking changes.
Here is the code with select statement:
$scope.emFac.entityQuery.from('Company').select('companyId, displayName');
Is there a way to retrieve only some columns of EF Model columns, and still track changes with Breeze.js, needed for database updates?
As you've discovered, Breeze treats the incoming data as plain objects instead of entities when you use select.
Your choices are:
On the server, Create a CustomerLite or similar object, and have a server endpoint that returns those without the need for select; OR
On the client, get the results from the query and create entities from each object, with status Unchanged
Example of #2:
var entities = [];
em.executeQuery(customerProjectionQuery).then(queryResult => {
queryResult.results.forEach(obj => {
// obj contains values to initialize entity
var entity = em.createEntity(Customer.prototype.entityType, obj, EntityState.Unchanged);
entities.push(entity);
});
})
Either way, you will need to ensure that your saveChanges endpoint on the server can handle saving the truncated Customer objects without wiping out the other fields.

Raw SQL with Entity Framework

I am trying to write a simple raw query with Entity Framework to my database:
[ResponseType(typeof(Customer))]
[Route("name/{name}")]
[HttpGet]
public List<Customer> GetCustomerName(string name)
{
//var results = db.Customers.SqlQuery("SELECT Name from dbo.Customer").Where(p => p.Name.Equals(name)).ToList();
var results = db.Customers.SqlQuery("SELECT Name from dbo.Customer WHERE Name = #Name",new SqlParameter("#Name",name)).ToList();
//var results = db.Customers.Where(p => p.Name.Equals(name));
return results;
}
The last Entity Framework query works just fine, but I want to do raw SQL to get something back simple because I have never gotten raw SQL with Entity Framework to work and I see all of these examples where people says it works for them. The top 2 var results do not work I get this error any help would be greatly appreciated. I am a Web API 2 newbie and I am just trying to learn it
So the error says a member of the type AccrRevAcct does not have a corresponding column. I am not sure what that means AccrRevAcct is a column on my database but so is Name and I just want the Name of my customer.
http://localhost:61280/api/Customers/name/1st MIDAMERICA CREDIT UNION
This is the call I make to my server and like I said it returns fine with the 3rd statement but that isn't raw SQL like I want to achieve. I only want to do this because I have some developers saying they can't get everything to work in EF I personally like it and haven't ran into this problem I want to show them fine just drop to raw SQL, but I need to show them I can make it work first lol.
If you are using SqlQuery on the DbSet you have to return a full instance. If you want to reshape the data like you are doing you need to use the SqlQuery<T> on the db.Database instead.
Example from https://msdn.microsoft.com/en-us/library/jj592907(v=vs.113).aspx
using (var context = new BloggingContext())
{
var blogNames = context.Database.SqlQuery<string>(
"SELECT Name FROM dbo.Blogs").ToList();
}
Honestly I think you are trying to solve the wrong problem. The last query is the one you should be using. If your developers can't get EF to work that is what needs to be fixed.

Entity framework performance when using methods in the select clause

I'm looking at the SQL generated when performing simple select queries. I'm using code first with the sample blog context from nuget.
If the following is run:
BlogContext _context = new BlogContext();
var comments = _context.Comments.Select(c => new CommentReadOnly {Author = c.Author});
var count = comments.Count();
The following SQL is produced:
SELECT
[GroupBy1].[A1] AS [C1]
FROM ( SELECT
COUNT(1) AS [A1]
FROM [dbo].[Comments] AS [Extent1]
) AS [GroupBy1]
Where the count is performed in the SQL which is expected.
However if I change the code to look like this:
BlogContext _context = new BlogContext();
var comments = _context.Comments.Select(c => new CommentReadOnly {Author = c.Author});
var count = comments.Count();
private CommentReadOnly ToCommentReadOnly(Comment comment)
{
return new CommentReadOnly
{
Author = comment.Author,
};
}
The following SQL is produced:
SELECT
[Extent1].[ID] AS [ID],
[Extent1].[PostID] AS [PostID],
[Extent1].[Text] AS [Text],
[Extent1].[Author] AS [Author]
FROM [dbo].[Comments] AS [Extent1]
With the count done in code.
The reason (I think) is because the first is returned as IQueryable where as the second is IEnumerable.
Is it possible to return the second query as IQueryable without executing the SQL?
The reason I ask is that I'm creating a generic repository layer that can query my entities and convert them to the required type (in the example above comment might have a couple of different 'readonly' objects). I don't want the SQL executing so early as paging may be done or other filtering in different situations.
I don't see any difference in those two queries. However, I guess you want to return a IQueryable object to the client so the client can perform further filtering and get the count from there.
You can simply return the object without doing the select and let the client do the rest.
return _context.Comments
The client can perform additional filtering on this IQueryable object
I think in your second query you execute the function ToCommentReadOnly() so this can't be done entirely in SQL and you end up with a Linq To Objects (IEnumerable).
But you state that you want to return an IQueryable from your Repository. This is not a recommended practice! The code to access the data should be hidden inside your repository otherwhise you will run into problems.
Say for example that your repository (which encapsulates your ObjectContext) goes out of scope after which you try to enumerate the IQueryable result the repository gave you. This will throw an error because the IQueryable can't be executed anymore.
If you expose an IQueryable from your Repository you give the end user of your Repository all the freedom they want in building their own queries, which is the thing you want to avoid by adding a repository!
So returning an IEnumerable from your Repository is a good thing :)

MVC 1.0 + EF: Does db.EntitySet.where(something) still return all rows in table?

In a repository, I do this:
public AgenciesDonor FindPrimary(Guid donorId) {
return db.AgenciesDonorSet.Include("DonorPanels").Include("PriceAdjustments").Include("Donors").First(x => x.Donors.DonorId == donorId && x.IsPrimary);
}
then down in another method in the same repository, this:
AgenciesDonor oldPrimary = this.FindPrimary(donorId);
In the debugger, the resultsview shows all records in that table, but:
oldPrimary.Count();
is 1 (which it should be).
Why am I seeing all table entries retrieved, and not just 1? I thought row filtering was done in the DB.
If db.EntitySet really does fetch everything to the client, what's the right way to keep the client data-lite using EF? Fetching all rows won't scale for what I'm doing.
You will see everything if you hover over the AgenciesDonorSet because LINQ to Entities (or SQL) uses delayed execution. When the query is actually executed, it is just retrieving the count.
If you want to view the SQL being generated for any query, you can add this bit of code:
var query = queryObj as ObjectQuery; //assign your query to queryObj rather than returning it immediately
if (query != null)
{
System.Diagnostics.Trace.WriteLine(context);
System.Diagnostics.Trace.WriteLine(query.ToTraceString());
}
Entity Set does not implement IQueryable, so the extension methods that you're using are IEnumerable extension methods. See here:
http://social.msdn.microsoft.com/forums/en-US/linqprojectgeneral/thread/121ec4e8-ce40-49e0-b715-75a5bd0063dc/
I agree that this is stupid, and I'm surprised that more people haven't complained about it. The official reason:
The design reason for not making
EntitySet IQueryable is because
there's not a clean way to reconcile
Add\Remove on EntitySet with
IQueryable's filtering and
transformation ability.