I'm facing a problem with breeze metadata. I developed a system with breeze controller. I see my model in the metadata including all navigation properties. When I fetch the data from the server I see my objects filled with the expected field, but the deserialized object on client side only includes the simple field without the collection.
I see in the metadata and the returned object from the server like following:
public partial class DesignType
{
public DesignType()
{
this.Product = new HashSet<Product>();
}
public int Id { get; set; }
public string Name { get; set; }
public string Code { get; set; }
public virtual ICollection<Product> Product { get; set; }
public virtual VisionType Vision { get; set; }
}
public partial class VisionType
{
public VisionType()
{
this.DesignType = new HashSet<DesignType>();
}
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<DesignType> DesignType { get; set; }
}
Here is the query code :
var query = breeze.EntityQuery.from("Designs");
breeze.manager.executeQuery(query).then(function (queryResult) {
callback(queryResult.results)
}).fail(function (queryFailed) {
error(queryFailed);
});
The results objects only contain the simple data properties and ignors the properties ICollection Product and Vision .
Any ideas.
Thanks in advance...
Your query only asks for the root type, DesignType, so that is all that should be returned. I'll assume that your server side method is not returning the related Product and Vision entities (which it could do but I'm betting that you're not making that happen).
So Breeze is doing what you asked.
If the client wants the related entities, it can ask for them with an expand clause:
breeze.EntityQuery.from("Designs")
.expand('Products, Vision')
Check out the documentation on queries and expand
Update 11 Dec 2013
If I understand your comment, (a) you now understand why you don't see Product because you are neither requesting products on the client nor pushing them out from the server, (b) your web api is including the related Vision instance and (b) you are seeing Vision data in the JSON response from the query.
The remaining mystery is why someDesignType.Vision is returning null.
Please read "Query response debugging" focusing in particular on the reference navigation property and the foreign key property on Product that points back to the DesignType. If you're still mystified, please show us how the details of the Vision navigation property as explained there.
Related
I made an MVC project which includes CRUD operations to all my classes, using default controllers and view pages which support those operations.
My new task was to make few API controllers to specific classes, which I have done correctly so far.
The problem is when a get request is requested, an entire object is returned with all its connections to other classes (which is correct!), but say I have this class:
public class VM{
public int Id { get; set; }
public string MacAddress { get; set; }
public string IpAddress { get; set; }
public DateTime? CreateDate { get; set; }
public string PrivateKey { get; set; }
public int AppId { get; set; }
public int CompanyId { get; set; }
}
I don't want the user to get the privateKey for instance, or ID. I would like the user to get all the rest, but certain information should NOT be sent.
What is the best practice to achieve that? Will making a new class which does not have those specific class members be the right answer?
Say tomorrow I would like to add another data member which will not be sent, will I have to make ANOTHER class?
I assume changing those specific data members' data to null just before sending the object back to the client is not the right answer, is it?
Just setting them to null is not the right answer indeed.
But generally you want your application to be as consistent as possible, and thus, for similar request you should return about the same types of fields/objects.
Thus a few (2 or 3) DTO (data transfer objects) should be sufficient.
If the project is of a small scale, or you just feel like being crazy you can always convert them to anonymous objects as follows:
List<VM> VMs = VMRepo.GetAll();
vms.ConvertAll(vm => new {vm.MacAddress, vm.IpAddress});
Or even give then custom names:
vms.ConvertAll(vm=> new {MAC= vm.MacAddress, IP= vm.IpAddress});
I'm new to MVC and trying to add/ edit records in master detail form. Both masterid and detailid are generated by oracle on insert of record. Thus when I try to call DBContext.SaveChanges() I get error that foreign key is violated and no primary row with id '0' can be found.
Below is the class description.
public class Master
{
public int MasterID { get; set; }
public string MasterTitle { get; set; }
public virtual IList<Detail> Details { get; set; }
}
public class Detail
{
public int DetailID { get; set; }
public int MasterID { get; set; }
public string DetailName { get; set; }
public virtual Master Master { get; set; }
}
Controller code
[HttpPost]
public ActionResult Create(MASTER masterrecord)
{
if (ModelState.IsValid)
{
db.MASTER.Add(masterrecord);
db.SaveChanges();
}
...
}
The primary key (masterid) will get meaningful values only after record is inserted to database. context.SaveChanges() at this point tries to save Client records too with '0' masterid. I searched every where couldn't find anything which could be of useful.
Though of saving only Master table first so that I can retrieve the masterid and us it with DETAIL model. however couldnt find anywhere how to do it using EF5 MVC ASP.NET
Can any one point me to right direction of provide with some working sample?
thanks
Siddhant
You might want to consider using GUIDs instead of ints for your PK. Then in your constructor for Master you can say MasterID = Guid.NewGuid();. This way you don't have to hit the database to find out what the next ID will be.
There is a pro and con list here http://www.codinghorror.com/blog/2007/03/primary-keys-ids-versus-guids.html
If you have set a breakpoint on the Create method and are getting a proper list in your Master object, it may be an issue with the Oracle provider.
As a workaround, you could try to change the method signature to accept your data like the following:
public ActionResult Create(MASTER masterrecord, List<Detail> details)
Then you could first save the masterrecord and subsequently add your details and save again. It's not optimal, but it may work.
Side note: change your IList to an ICollection.
I have an MVC app using EF code first. I add a user to the system and enter pension details, part of this is a dropdown linked to a model called PensionBenefitLevel. This is the model -
[Key]
public int PensionBenefitLevelID { get; set; }
public string DisplayText { get; set; }
public int EmployeePercentage { get; set; }
public int EmployerPercentage { get; set; }
public virtual ICollection<Pension> Pension { get; set; }
When registered I have the PensionBenefitLevelID that came from the dropdown, but in my controller I was to peform a calculation using the EmployerPercentage value that is related to that ID. Can anyone point me in the correct direction?
Do I need to create a variable in the controller and use a linq query to get that value back? I've not been able to find any examples of something similar so if you could point me to one that would be great too.
If I understand the question correctly, you want to get back the entity corresponding to PensionBenefitLevelID and perform a calculation on the EmployerPercentage field.
Since you haven't mentioned what pattern you are using with EF (repository, unit of work, etc.) I can only give you a general answer:
var entity = [Your DB Context].[Your Entity].GetById(pensionBenefitLevelID);
if(entity != null)
{
[Calculation]
}
I am trying to send a simple object (AjaxSubmission) from a form to a Web API controller used to edit tables.
AjaxSubmission always has the same fields. One field, "data" refers to another simple object with accessors for the specific table (Employees or Vendors examples below).
public class AjaxSubmission
{
public string action { get; set; }
public string table { get; set; }
public string id { get; set; }
// ...
//// The following may be any other custom class
public Employees data { get; set; } // Could be Vendors or whatever
}
// Stored in AjaxSubmission (or so I hope)
public class Employees
{
public string name { get; set; }
public float salary { get; set; }
public long id { get; set; }
}
// Stored in AjaxSubmission
public class Vendors
{
public string dba { get; set; }
public int accountNum { get; set; }
public int zipcode { get; set; }
}
My controller gets the data like so:
public EditorServerResponse Put(AjaxSubmission ajaxSubmission = null) {
// Handle the data
}
When I make "data" an Object or Dynamic, it shows up as an empty object. I can't "as" it to Employees or Vendors because it doesn't store anything.
I suspect this is a limitation of the serializer. MVC4 uses JSON.NET for JSON, but the data is sent as "Content-Type: application/x-www-form-urlencoded; charset=UTF-8".
I cannot easily change the way data is sent because that is how the Datatables editor plug-in does its business. I think it's a reasonable way to send data and a reasonable problem for .NET to be able to handle.
I can get the data I need if I make a distinct class for each data type that AjaxSubmission might contain, but each would be a duplicate other than one line of code. That horribly violates the DRY principle.
My question is: How can I send AjaxSubmission without Repeating Myself? Is .NET capable of such a thing?
Edit:
Fiddler says the data looks like:
action edit
table
id row_4
data[amu] 49
data[chemicalFormula] BF2
data[commonName] Boron difluoride
data[status] Y
data[notes]
The raw data is:
action=edit&table=&id=row_4&data%5Bamu%5D=49&data%5BchemicalFormula%5D=BF2&data%5BcommonName%5D=Boron+difluoride&data%5Bstatus%5D=Y&data%5Bnotes%5D=
(This is different from my simplified examples but similar)
Am having trouble finding a clear answer to my situation when searching Stack Overflow and Google, hopefully someone can point me in the right direction.
My Situation
I want to be able to use a single edit form (in a single View) to update a 3-level-deep hierarchical entity using ASP.NET MVC 3 and Entity Framework 4 CTP (Code-first) - the model consists of Services, which can have many Service Options, which in Turn can have many Inventory Items.
I was expecting to be able to use MVCs default model binder (via TryUpdateModel) to:
Update an existing 'Service' record
Add/Update/Delete 'Service Option' records (attached to the Service) depending on posted values
Add/Update/Delete 'Inventory' records (attached to each Service Option) depending on posted values
My Model
[Bind(Include="Name, ServiceOptions")]
public class Service {
[Key]
public int ServiceID { get; set; }
public string Name { get; set; }
public DateTime DateCreated { get; set; }
public virtual ICollection<ServiceOption> ServiceOptions { get; set; }
}
[Bind(Include="ServiceOptionID, Description, Tags")]
public class ServiceOption {
[Key]
public int ServiceOptionID { get; set; }
public int ServiceID { get; set; } /* parent id reference */
public string Description { get; set; }
public virtual ICollection<Inventory> InventoryItems { get; set; }
}
[Bind(Include = "InventoryID, Description")]
public class Inventory {
[Key]
public int InventoryID { get; set; }
public int ServiceOptionID { get; set; } /* parent id reference */
public string Description { get; set; }
}
Ideal Controller Method:
[HttpPost]
public ActionResult EditService(int id) {
Service service = db.Services.Single(s => s.ServiceID == id);
TryUpdateModel(service); // automatically updates child and grandchild records
if (ModelState.IsValid) {
db.SaveChanges();
return RedirectToAction("Index");
}
return View(service);
}
Is there a way to achieve this utopian dream, or am I barking up the wrong tree? I'm open to using another technology (such as normal EF4, Automapper etc)
Thanks in advance!
With just the default model binder? Probably not.
With a custom one? Probably.
However your issue won't be the model binder itself. Your issue will be that EF and ORMs and ( I think ) in general do not consider removing an item from a collection as a delete operation. In effect what you are telling the ORM is the relationship does not exist, not that a child row needs to be deleted. Depending on your mappings you'll usually get an error like "A referential integrity constraint violation occurred". This won't be because of code first this is just how EF works.
EF works this way by design and is really important for more complex relationships such as when you have m2m relationships which reference other m2m relationships. You really want EF to be able to disambiguate calls for removal of a relationship and calls to remove a row entirely.
Also, IMHO, this technique is also bad because your letting the piece of code responsible for mapping http values also dictate how objects should be persisted. This is a bad move. I consider delete operations a pretty sacrosanct act and shouldn't be left to the ModelBinder alone. Without soft deletes or logging deleting objects should be considered "serious business".