I am doing a simple projection query in Breeze:
var p1 = new Predicate('ID', 'eq', articleID);
var p2 = new Predicate('isDeleted', '!=', true);
var p3 = new Predicate('isAutoSave', '!=', true);
var query = EntityQuery.from(entityNames.article)
.where(p1.and(p2.and(p3)))
.select('Code, Description, ImageFileName, Notes, SupplierDistance')
I then used the entity mapper to create a partial entity to put into an observable to return back to the function. All was good.
Then I realised I needed a country name from a related table, so I first tried ".expand" and was told that Breeze couldn't do "expand" and "select" simultaneously. No problem, will select the related record directly:
.select('Code, Description, Country.CountryName, ImageFileName, Notes, SupplierDistance')
But as there is no "Country_CountryName" property on the entity I am creating a partial of, the mapping fails (unsurprisingly) with an "undefined is not a function" error. How am I able to include the countryName field from the related table in this way where I cannot map the entity?
I tried stuffing the javascript object returned by the query into my observable but that fails with an "object is not a function" error so that's no good either.
I decided that the entity mapping was unnecessary in the end and reverted to a simple projection query where I manually handled the "expand".
Related
The code below returns a single record from my database, as-expected. However, it fails to track changes in the UI. I'm binding myObject's properties to various fields using angularjs. Everything initially loads fine, but if I make changes to the object and use breeze's EntityManager.saveChanges(), it doesn't detect than anything has changed. I can create a new entity and save it just fine, but trying to understand how to handle updates. Do I need to detach the entity after I retrieve it, then reattach and save?
Or is this the wrong way to assign a retrieved entity to my javascript (using TypeScript) object?
myObject = data.results[0];
let query = breeze.EntityQuery.from("myTable").where('id', '==', incomingId).expand(['relatedTable']);
dataService.executeQuery(query).then((data) => {
this.myObject = data.results[0];
});
I had to add '.toType("myType")' clause onto the query. I used 'metadataStore.registerEntityTypeCtor' to register my types in the EntityManager, but this step was still necessary for me, which I don't entirely understand.
let query = breeze.EntityQuery.from("myTable").where('id', '==', incomingId).expand(['relatedTable']).toType("myType");
dataService.executeQuery(query).then((data) => {
this.myObject = data.results[0];
});
Edit: I also found that using the EFContextProvider to do my querying improved my results and lessened issues incredibly. In the past, I had only used the Context, and while it worked, my entity types were not understood as well by Breeze on the client side.
readonly EFContextProvider<Context> _contextProvider = new EFContextProvider<Context>();
[HttpGet]
public IQueryable<Dispute> Disputes()
{
return _contextProvider.Context.Disputes;
}
I am new to entity framework and I am trying to get my head around it. I am used to writing stored procedures which have all the data I need on a example by example basis.
I am under the impression that I can get all values from a particular table including the foreign key values direct using entity framework without having to write a select query which joins the data.
I have the following in my controller
public ActionResult Patient()
{
using (var context = new WaysToWellnessDB())
{
var patients = context.Patients.ToList();
return View(patients);
}
}
In my view I have the following
#foreach (var item in Model)
{
<p>
#item.FirstName #item.Surname #item.Gender.GenderDesc
</p>
}
I have two tables, Patient and Gender, GenderId is a foreign key which I am trying to get the GenderDesc from that table.
I am getting the following message
The ObjectContext instance has been disposed and can no longer be used for operations that require a connection.
Can someone explain why I cannot access GenderDesc. It does work if I remove the using() around my context, but I don't really want to leave that open, is there a way to get this to work still having the using around?
Thanks in advance.
Correct, you have disposed of the context as it is within a using statement, so anything you try to access from then on will not be able to be lazy loaded. The disadvantage with lazy loading is that it will perform a query for the gender for every patient you are iterating over, which is handy, but bad! I would load the related table at query time using Include.
You'll need a new import:
using System.Data.Entity;
And then include the related table:
var patients = context.Patients.Include(p => p.Gender).ToList();
That will result in a query which will join to your "Gender" table and you should be able to output item.Gender.GenderDesc in your view.
I have 1 entity 'Parameters' that keeps all values for different dropdown lists etc..
When I bundle these through the breeze lookups controller, they all get loaded nicely.
But since the manager maps them against the metadata, they all end up in 1 list.
How can I seperate them?
thanks!
I had the same issue using and resolved by:
Having breeze load the entity (Lookups) with only the values that I needed (all of my source values also had a category Id that I allowed me to identify the correct grouping.
function getLookups() {
return EntityQuery.from('Lookups')
.using(manager).execute()
.then(processLookups)
.fail(queryFailed);
}
Once I had the "Lookup" entity loaded with breeze, I loaded the arrays in the view model by executing a query on the lookup entity and loading that array with the correct values.
methods(datacontext.getMethods());
var getMethods = function () {
var query = EntityQuery
.from('Lookups')
.where('Cat_Id', 'eq', 375);
return manager.executeQueryLocally(query);
};
In the view I bound the select to the view model array and set the value to the navigation property that tied back to the SQL lookup table.
Getting an error client side with breeze: "Cannot call method 'map' of undefined" when trying to pull over some data. The difference between this action and one that works is that this action is calling a stored procedure and returning ObjectResult<T> instead of DbSet<T>.
Might this be why I get an error? Using Chrome Developer tools, I do see that the breeze controller is returning json data.
I have created a complex model type in the edmx for mapping the rows returned from the stored procedure.
The action in the breeze controller has a return type of IEnumerable<T>.
I experienced the same error when using an EF complex type. A workaround was to create a view in my database instead of using a complex type, set the stored procedure to return a type of the new view which had a primary key and then it worked. It would seem that breeze requires entities to have a primary key defined.
Hm... not quite sure what is happening, so just guessing here, but try adding an AsQueryable() to the result returned, and changing the result type to a IQueryable.
We don't have any stored proc tests for breeze yet, but this is impetus for me to add some :)
I had the very same issue, but thank God I figured out a solution. Instead of using a stored procedure, you should use a view, as Breeze recognizes views as DbSet<T>, just like tables. Say you have a SQL server table that contains two tables Customers and Orders.
Customers (**CustomerId**, FirstName, LastName)
Orders (OrderId, #CustomerId, OrderDate, OrderTotal)
Now, say you want a query that returns orders by CustomerId. Usually, you would do that in a stored procedure, but as I said, you need to use a view instead. So the query will look like this in the view.
Select o.OrderId, c.CustomerId, o.OrderDate, o.OrderTotal
from dbo.Orders o inner join dbo.Customers c on c.CustomerId = o.CustomerId
Notice there is no filtering (where ...). So:
i. Create a [general] view that includes the filtering key(s) and name it, say, OrdersByCustomers
ii. Add the OrdersByCustomers view to the entity model in your VS project
iii. Add the entity to the Breeze controller, as such:
public IQueryable<OrdersByCustomers> OrdersByCustomerId(int id)
{
return _contextProvider.Context.OrdersByCustomers
.Where(r => r.CustomerId == id);
}
Notice the .Where(r => r.CustomerId == id) filter. We could do it in the data service file, but because we want the user to see only his personal data, we need to filter from the server so it only returns his data.
iv. Now, that the entity is set in the controller, you may invoke it in the data service file, as such:
var getOrdersByCustomerId = function(orderObservable, id)
{
var query = breeze.EntityQuery.from('OrdersByCustomerId')
.WithParameters({ CustomerId: id });
return manager.executeQuery(query)
.then(function(data) {
if (orderObservable) orderObservable(data.results);
}
.fail(function(e) {
logError('Retrieve Data Failed');
}
}
v. You probably know what to do next from here.
Hope it helps.
New to Entity Framework .Using EF4. I have found articles and managed to use stored procedures to return a list of entities.
But cannot see/work out how you return a single entity.
Given that I have a stored procedure "GetCustomerById" that return a single customer How do I map it?
Using the Model Browser I right click on "Function Import" and I have added my StoredProcedure
however whatever I select does not seem to return a "Single Entity"
Am I missing the obvious?
thanks a lot for any link or suggestions
When you do Function Import you need to select the entity your SP returns from the drop down (i.e. Customer). The catch is EF does NOT directly returns Customer object as per your selection but System.Data.Objects.ObjectResult which implements IEnumerable.
To be more specific, here is the generated code for your function:
public ObjectResult<Customer> GetCustomerById(Nullable<global::System.Int32> Id)
That's because EF has no idea if your SP returns a single record or a list of them so it wraps the result inside ObjectResult. You can enumerate through this to get your Customer entity like any other IEnumerable object. For example:
Customer myCustomer = context.GetCustomerById(1).First();