Navigation property data retrieved yet cannot be accessed - breeze
I have a situation which seems simple yet I cannot resolve it nor find similar situations resolved, please help :-)
The following 2 classes on the server:
public class Category
{
[Key]
public int CategoryId { get; set; }
[Required]
[MaxLength(256)]
public string Name { get; set; }
public Int16? Order { get; set; }
[ForeignKey("ParentCategoryId")]
public Category ParentCategory { get; set; }
public int? ParentCategoryId { get; set; }
[ForeignKey("ParentCategory")]
[InverseProperty("ParentCategory")]
public List<Category> SubCategories { get; set; }
[ForeignKey("ProductId")]
public List<Product> Products { get; set; }
}
public class Product
{
[Key]
public int ProductId { get; set; }
[Required]
[MaxLength(256)]
public string Name { get; set; }
[MaxLength(1024)]
public string Desc { get; set; }
public int ShopPrice { get; set; }
public int WebPrice { get; set; }
[MaxLength(32768)]
public string ProductDetails { get; set; }
}
a simple controller method:
[HttpGet]
public IQueryable<Category> Categories()
{
return _contextProvider.Context.Categories;
}
when I use the following url:
http://localhost:49733/api/breeze/Categories?$filter=CategoryId%20eq%2010&$expand=Products
I get the following data:
[{"$id":"1","$type":"Photoshwartz.Models.Category, Photoshwartz","CategoryId":10,"Name":"תת קטגוריה .1.1","Order":2,"ParentCategory":null,"ParentCategoryId":1,"SubCategories":null,"Products":[{"$id":"2","$type":"Photoshwartz.Models.Product, Photoshwartz","ProductId":1,"Name":"מוצר 1.1.1","Desc":"תאור המוצר...","ShopPrice":328,"WebPrice":295,"ProductDetails":"abcdef...."},{"$id":"3","$type":"Photoshwartz.Models.Product, Photoshwartz","ProductId":2,"Name":"מוצר 1.1.2","Desc":"תאור המוצר...","ShopPrice":570,"WebPrice":513,"ProductDetails":"abcdef...."},{"$id":"4","$type":"Photoshwartz.Models.Product, Photoshwartz","ProductId":3,"Name":"מוצר 1.1.3","Desc":"תאור המוצר...","ShopPrice":579,"WebPrice":521,"ProductDetails":"abcdef...."},{"$id":"5","$type":"Photoshwartz.Models.Product, Photoshwartz","ProductId":4,"Name":"מוצר 1.1.4","Desc":"תאור המוצר...","ShopPrice":598,"WebPrice":538,"ProductDetails":"abcdef...."},{"$id":"6","$type":"Photoshwartz.Models.Product, Photoshwartz","ProductId":5,"Name":"מוצר 1.1.5","Desc":"תאור המוצר...","ShopPrice":362,"WebPrice":325,"ProductDetails":"abcdef...."},{"$id":"7","$type":"Photoshwartz.Models.Product, Photoshwartz","ProductId":6,"Name":"מוצר 1.1.6","Desc":"תאור המוצר...","ShopPrice":484,"WebPrice":435,"ProductDetails":"abcdef...."},{"$id":"8","$type":"Photoshwartz.Models.Product, Photoshwartz","ProductId":7,"Name":"מוצר 1.1.7","Desc":"תאור המוצר...","ShopPrice":416,"WebPrice":374,"ProductDetails":"abcdef...."},{"$id":"9","$type":"Photoshwartz.Models.Product, Photoshwartz","ProductId":8,"Name":"מוצר 1.1.8","Desc":"תאור המוצר...","ShopPrice":281,"WebPrice":252,"ProductDetails":"abcdef...."},{"$id":"10","$type":"Photoshwartz.Models.Product, Photoshwartz","ProductId":9,"Name":"מוצר 1.1.9","Desc":"תאור המוצר...","ShopPrice":213,"WebPrice":191,"ProductDetails":"abcdef...."}]}]
as you can see, there is a navigation property called 'Products' which contains 9 items. However, when I try to access this data via the following code I get the non-navigation properties (e.g. 'name()' and 'order()'), but 'products' is undefined (or 'Products' or 'products()' or 'Products()'...). I put a breakpoint in the 'querySucceededAppend' to see this in 'data.results[0]'.
var query = EntityQuery
.from("Categories")
.where("categoryId", "==", categoryId)
.expand("products");
manager.executeQuery(query).then(querySucceededAppend)
Any suggeestions ?
Thanks !
Elior
Change your expand method to 'Products as shown -
var query = EntityQuery
.from("Categories")
.where("categoryId", "==", categoryId)
.expand("Products");
manager.executeQuery(query).then(querySucceededAppend)
When Products are returned you will access them via something like
someObservable = ko.observabled(data.results[0])
console.log(someObservable().products());
Related
ViewModel for multiple tables without links between tables
I'm trying to write a View Model in an ASP.NET MVC5 project to show data from different tables on a form that the user can then edit and save. I'm using the following :- VS 2017, c#, MySQL Database, Entity Framework 6.1.3, MySQL Connector 6.9.9, Code First from Database (existing database that I can't change) To complicate matters, there are no links between the tables in the database, so I cannot work out how to create a suitable View Model that will then allow me to save the changes. Here are the 4 table models :- public partial class evc_bearer { [Key] [Column(Order = 0] [DatabaseGenerated(DatabaseGeneratedOption.None)] public long evcid { get; set; } [Key] [Column(Order = 1] [DatabaseGenerated(DatabaseGeneratedOption.None)] public long bearerid { get; set; } public int vlan { get; set; } [Column("ref")] public string _ref { get; set; } [Required] public string port { get; set; } [Required] public string endpoint { get; set; } } public partial class bearer { [Key] public long id { get; set; } [Column("ref")] [Required] public string _ref { get; set; } public string name { get; set; } public long? site { get; set; } public long? provider { get; set; } public long? mtu { get; set; } public float? rental { get; set; } public int? offsiteprovider { get; set; } public float? offsiteproviderrental { get; set; } public bool? aend { get; set; } public int? equipmentport { get; set; } public string orderref { get; set; } public string offsiteref { get; set; } public string notes { get; set; } public float? bookingfactor { get; set; } } public partial class evc { [Key] public long id { get; set; } [Required] public string type { get; set; } public byte servicetype { get; set; } public byte cos { get; set; } public int cir { get; set; } public int pir { get; set; } public bool burst { get; set; } [Column("ref")] public string _ref { get; set; } public string orderref { get; set; } public byte state { get; set; } public string notes { get; set; } public float? rental { get; set; } } public partial class evc_provider { [Key] public long id { get; set; } [Required] public string provider { get; set; } } This is the View Model I tried writing :- public partial class evcBearersVM { [Key] [Column(Order = 0)] public long evcid { get; set; } [Key] [Column(Order = 1)] public long id { get; set; } [Column("ref")] public string b_ref { get; set; } public string b_name { get; set; } public string ep_provider { get; set; } public int eb_vlan { get; set; } public string eb_port { get; set; } public string eb_endpoint { get; set; } } This is the Linq query I used to populate the View Model :- IQueryable<evcBearersVM> data = from eb in csdb.evc_bearers join b in csdb.bearers on eb.bearerid equals b.id join ep in csdb.evc_providers on b.provider equals ep.id join e in csdb.evcs on eb.evcid equals e.id where (eb.evcid == evcid && b.id == id) select new evcBearersVM { evcid = eb.evcid, id = b.id, b_ref = b._ref, b_name = b.name, ep_provider = ep.provider, eb_vlan = eb.vlan, eb_port = eb.port, eb_endpoint = eb._ref }; So the query works and joins the tables to get the data I need and I can display this date in various views as needed. What I now need to do is be able to edit a row and save it back to the database. I have an Edit View that is showing the data I need but I'm not sure how to save changes given that it's a View Model and the DB Context isn't aware of it. Grateful for any help.
What you should do is, use the same view model as your HttpPost action method parameter and inside the action method, read the entities you want to udpate using the Id's (you can get this from the view model, assuming your form is submitting those) and update only those properties you need to update. [HttpPost] public ActionResult Edit(evcBearersVM model) { var b = csdb.bearers.FirstOrDefault(a=>a.id==model.id); if(b!=null) { b.name = model.b_name; b._ref = model.b_ref; csdb.SaveChanges(); } // Update the other entity as well. return RedirectToAction("Index"); }
Want to join two tables on primary key, display the results in one view
IQueryable<Product> product = objContext.Set<Product>().Include(p => p.Categories.Name).Where(p => p.Id == 2); As per the current view, I'm getting an error. It says add other model with their properties. i.e. to include Category model and corresponding Name property. #model IEnumerable<>crudOneToMany.Models.Product> using viewmodel, is it possible to join two tables? View Error A specified Include path is not valid. The EntityType 'crudOneToMany.Models.Category' does not declare a navigation property with the name 'Name'. public class Product { public int Id { get; set; } public string Name { get; set; } public string Description { get; set; } public int CategoryId { get; set; } public virtual Category Categories { get; set; } } public class Category { public int Id { get; set; } public string Name { get; set; } public ICollection<Product> Products { get; set; } } public class ProductDBContext : DbContext { public ProductDBContext() : base("ProductDBContext") { } public DbSet<Product> Products { get; set; } public DbSet<Category> Categories { get; set; } protected override void OnModelCreating(DbModelBuilder modelBuilder) { modelBuilder.Entity<Product>().HasRequired(o => o.Categories).WithMany(o => o.Products).HasForeignKey(o => o.CategoryId); base.OnModelCreating(modelBuilder); } }
Your problem is here: .Include(p => p.Categories.Name) Instead you should write .Include(p => p.Categories) This means that in output there will be loaded Categories navigation collection to product. Name is simple string property (is not navigation property so it should not be included)
Here is the proposed ViewModel for you. ProductViewModel.cs public class ProductViewModel { public int Id { get; set; } [Required(ErrorMessage = "required")] public string ProductName { get; set; } public Category Category { get; set; } public ICollection<Category> Categories { get; set; } }
How to include () in query
iam have two modal i I'm trying to include all Post that belong the User. However, I keep getting the following debug error: Error 58 Cannot convert lambda expression to type 'string' because it is not a delegate type please see pic public IList<User> GetSliderImages() { var q = db.Users.Include(x=>x.Post).OrderByDescending(x => x.FPersonalUser).Where(x => x.typemanger == 1).ToList(); return q; } public class User { [Key] public int ID_User { set; get; } public Int16 ID_post { set; get; } public bool Fbofd { set; get; } public string FuserName { set; get; } public bool Foffice { set; get; } public byte[] FPicaddress { set; get; } **public IList<Post> _post { set; get; }** } public partial class Post { [Key] public int ID_Post { set; get; } public string FNamePost { set; get; } }
public virtual ICollection<Post> Post{ get; set; } please use look like this for using relationship between two table then use include syntax.
Getting Error: "A specified Include path is not valid. The EntityType Field' does not declare a navigation property"
Created method: public List<Field> GetScheduleDetails() { var schedulefields = DBcontextFactory.Context.Set<Field>).Include("ScheduleField").ToList(); } With the above method i am trying to fetch all joined(field.fieldid=schedulefield.fieldid) records from both tables. The field table is related with schedulefield table. Sorry if i am not familiar with technical terms. Field Model: public partial class Field : DOIEntity { public Field() { this.FilerResponses = new HashSet<FilerResponse>(); this.ScheduleFields = new HashSet<ScheduleField>(); } public int FieldId { get; set; } public string FieldDisplayName { get; set; } public int FieldTypeId { get; set; } public string HelpText { get; set; } public Nullable<bool> OtherTextAllowed { get; set; } public Nullable<int> ChoiceGroupId { get; set; } public virtual FieldType FieldType { get; set; } public virtual ICollection<FilerResponse> FilerResponses { get; set; } public virtual ICollection<ScheduleField> ScheduleFields { get; set; } } ScheduleField Model: public partial class ScheduleField { [Key] public int ScheduleId { get; set; } public int FieldId { get; set; } public byte SortOrder { get; set; } public Nullable<bool> IsMandatory { get; set; } public Nullable<int> ParentFieldId { get; set; } public Nullable<int> ParentChoiceId { get; set; } public virtual Field Field { get; set; } public virtual Schedule Schedule { get; set; } } When I call the method I am getting this error: A specified Include path is not valid. The EntityType 'WorldBank.DOI.Data.Field' does not declare a navigation property with the name 'ScheduleField'. Why am I getting this error?
You have to use the property name of the Field class in the Include string: public List<Field> GetScheduleDetails() { var schedulefields = DBcontextFactory.Context.Set<Field>).Include("ScheduleFields").ToList(); } This will eager load the ScheduleField objects associated with the Field objects. Note, you can also eager load many levels. For example, if you want to eager load the schedules of the ScheduleField object as well you would do this: public List<Field> GetScheduleDetails() { var schedulefields = DBcontextFactory.Context.Set<Field>).Include("ScheduleFields.Schedule").ToList(); }
PagedList in MVC3 with IQueryable
I can't understand what i'm doing wrong. Every time I'm getting this error: The entity or complex type 'BusinessLogic.CompanyWithDivisionCount' cannot be constructed in a LINQ to Entities query. I need to get info from 'Company' table and divisions count of each company from 'Division' table, and then make PagedList. Here is my 'Company' table: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.ComponentModel.DataAnnotations; using BusinessLogic.Services; using BusinessLogic.Models.ValidationAttributes; namespace BusinessLogic.Models { public class Company { public Company() { Country = "US"; Status = true; } public int Id { get; set; } [Required] [UniqueCompanyName] public string Name { get; set; } public string Street { get; set; } public string City { get; set; } public string State { get; set; } public int Zip { get; set; } public string Country { get; set; } public string ContactInfo { get; set; } [Required] public DateTime EffectiveDate { get; set; } public DateTime TerminationDate { get; set; } public bool Status { get; set; } [Required] public string URL { get; set; } public string EAP { get; set; } public string EAPCredentials { get; set; } public string BrandingColors { get; set; } public string Comments { get; set; } } } Here is my domain model: public class Company { public Company() { Country = "US"; Status = true; } public int Id { get; set; } [Required] [UniqueCompanyName] public string Name { get; set; } public string Street { get; set; } public string City { get; set; } public string State { get; set; } public int Zip { get; set; } public string Country { get; set; } public string ContactInfo { get; set; } [Required] public DateTime EffectiveDate { get; set; } public DateTime TerminationDate { get; set; } public bool Status { get; set; } [Required] public string URL { get; set; } public string EAP { get; set; } public string EAPCredentials { get; set; } public string BrandingColors { get; set; } public string Comments { get; set; } } public class CompanyWithDivisionCount: Company // I'm using this { public int DivisionCount { get; set; } } Here is my controller: public ActionResult CompaniesList(int? page) { var pageNumber = page ?? 1; var companies = companyService.GetCompaniesWithDivisionsCount2(); var model = companies.ToPagedList(pageNumber, PageSize); return View(model); } And here is my service part: public IQueryable<CompanyWithDivisionCount> GetCompaniesWithDivisionsCount2() { return (from c in dataContext.Companies.AsQueryable() select new CompanyWithDivisionCount { Id = c.Id, Name = c.Name, Status = c.Status, EffectiveDate = c.EffectiveDate, URL = c.URL, EAP = c.EAP, EAPCredentials = c.EAPCredentials, Comments = c.Comments, DivisionCount = (int)dataContext.Divisions.Where(b => b.CompanyName == c.Name).Count() }); } } Thanks for help!!!
Creator of PagedList here. This has nothing to do with PagedList, but rather is an Entity Framework issue (I'm no expert on Entity Framework, so can't help you there). To confirm that this is true, write a unit test along the following lines: [Test] public void ShouldNotThrowAnException() { //arrange var companies = companyService.GetCompaniesWithDivisionsCount2(); //act var result = companies.ToList(); //assert //if this line is reached, we win! no exception on call to .ToList() }
I would consider changing you data model if possible so that instead of relating Companies to Divisions by name strings, instead use a properly maintained foreign key relationship between the two objects (Divisions should contain a CompanyID foreign key). This has a number of benefits (including performance and data integrity) and will almost certainly make your life easier moving forward if you need to make further changes to you app (or if any company ever decides that it may re-brand it's name). If you create a proper foreign key relationship then your domain model could look like public class Company { ... public virtual ICollection<Division> Divisions{ get; set; } public int DivisionCount { get { return this.Divisions.Count() } } ... }