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.
Related
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'm trying to limit the amount of data coming across when implementing Lookup Lists in Breeze.JS. The Lookup Lists sample uses queries that results in full objects but I would like to project the entities to fewer properties (e.g. primary key, foreign keys, and a descriptor property) and still have Breeze.JS recognize the entity type on the client. I know how to do the projections from the client to get partials but how would I do that with Lookup Lists (either from the client or the server Web API)?
You might satisfy your intentions with a custom JsonResultsAdapter.
You're probably wondering "What is a JsonResultsAdapter?"
That's what breeze uses to interpret the JSON arriving from the server. You can read about here and here.
Perhaps more helpful is to look at the adapter in the Web API dataservice and at the example adapter from the "Edmumds" sample.
The Edmunds sample demonstrates translating a JSON source that you don't control into breeze entities.
In this case, your JsonResultsAdapter would look at each node of JSON and say "this is a Foo, this is a Bar, and that one is a Baz". Accordingly, for each of these nodes it would return { entityType: "Foo" }, return { entityType: "Bar" }, and return { entityType: "Baz" }
Now breeze knows what to do and creates corresponding entities out of the Lookups payload.
Remember to mark these entities as partial, in the same way you would if you had made a projection query that targeted a single entity type.
Fortunately, the Lookups query returns the container object that holds the Foo, Bar, and Baz collections. So you can iterate over these and mark them partial right there in the query success callback.
Once you wrap your head around THAT ... you'll want to know how to put your custom JsonResultsAdapter to work in the Lookups query ... and ONLY in the Lookups query.
You can enlist that JsonResultsAdapter exclusively for your Lookups query with a using clause.
Here's an example:
var jsa = new breeze.JsonResultsAdapter({
name: 'myLookupsJsa',
visitNode: function() {...}
});
query = query.using(jsa);
Is this overkill? Would you be better off making three trips?
Only you will know. I would like to hear from you when you try it ... and give us your suggestions on how we might make this easier in a general way.
In the lookup lists example the controller action looks like this:
[HttpGet]
public object Lookups() // returns an object, not an IQueryable
{
var regions = _contextProvider.Context.Regions;
var territories = _contextProvider.Context.Territories;
var categories = _contextProvider.Context.Categories;
return new {regions, territories, categories};
}
You could reduce the footprint using a server-side projection like this:
[HttpGet]
public object Lookups() // returns an object, not an IQueryable
{
var regions = _contextProvider.Context.Regions
.Select(x => new { id = x.RegionId, name = x.RegionName });
var territories = _contextProvider.Context.Territories
.Select(x => new { id = x.TerritoryId, name = x.TerritoryName });
var categories = _contextProvider.Context.Categories
.Select(x => new { id = x.CategoryId, name = x.CategoryName });
return new {regions, territories, categories};
}
This approach does not answer this part of your question:
and still have Breeze.JS recognize the entity type on the client
Not sure what the solution or use case is for this piece.
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".
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.
I have the following sample code which gets a list of values from a table in the DB and binds them to a checkbox list.
var db = new DBContext();
db.Entity1.ToList().ForEach(
x => CheckBoxList1.Items.Add(new ListItem(x.Value, x.ID));
I have about 10 checkboxlists like these and I dont want to repeat the code. I'm trying to extract a method out of it and use it for all checkboxes. Is it possible to load an entity by a string name? Something like -
db.Load("Entity1").ToList().ForEach...
So I can pass in the entity name and the checkbox list and do the foreach loop in the method and bind the items, like this -
void BindValues(string entityName, CheckBoxList checkBoxList)
{
db.Load("Entity1").ToList().ForEach(
x => checkBoxList.Items.Add(new ListItem(x.Value, x.ID)));
}
Thank you.
In Code First the DbContext exposes a .Set() or .Set(Type) method to get a handle on the table. So assuming straight EF exposes the same, and you are happy to access your lists by their entity type rather than a string, this would work for you.