Breeze.js and PreserveReferencesHandling serializing failure - breeze

I encounter a problem with deserializing entities in client side with breeze.js.
My data model entity has one to many relation to other entities (A has ICollection of B)
When I make a query , I see the data returned from the server include $ref= # , I understood breeze uses this to identify same objects returned from the server.
But in client side all those entities with $ref=# doesn't deserialized properly I get this function () { return mc.refMap[node]} insted to get the real object in client side .
Here is my object structure :
public partial class Product
{
public Product()
{
this.ProductCatalogue = new HashSet<ProductCatalogue>();
this.DiameterRanges = new HashSet<DiameterRanges>();
this.Product_Children = new HashSet<Product>();
}
public int Id { get; set; }
public string Code { get; set; }
public virtual ICollection<ProductCatalogue> ProductCatalogue { get; set; }
public virtual ICollection<DiameterRanges> DiameterRanges { get; set; }
public virtual Product Product_Parent { get; set; }
}
public partial class DiameterRanges
{
public int Id { get; set; }
public double MinSPH { get; set; }
public double MaxSPH { get; set; }
public double MinCyl { get; set; }
public double MaxCyl { get; set; }
public short MinDiameter { get; set; }
public short MaxDiameter { get; set; }
public int Product_Id { get; set; }
public virtual Product Product { get; set; }
}
Nothing special in my server side query : Context.Product.Include("DiameterRanges");
Any idea to figure out this problem .
Thanks in advance ....

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");
}

Update hierarchy model in Entity Framework

I have two model classes:
Request:
public partial class Request
{
public long Id { get; set; }
public string Username { get; set; }
public string Description { get; set; }
public System.DateTime CreateDate { get; set; }
public long DeviceId { get; set; }
public bool IsFinalized { get; set; }
public Nullable<long> ParentId { get; set; }
public virtual Device Device { get; set; }
}
Device:
public partial class Device
{
public Device()
{
this.Requests = new List<Request>();
}
public long Id { get; set; }
public string Serial { get; set; }
public string AssetNumber { get; set; }
public System.DateTime CreatedDate { get; set; }
public virtual ICollection<Request> Requests { get; set; }
}
I have to update the models I use this method
public void Update(RequestViewModel viewModel)
{
var entity = _mappingEngine.Map<Request>(viewModel);
_requests.Attach(entity);
_uow.Entry(entity).State = EntityState.Modified;
}
but only Request model is updated after calling the Update method. I want to update both models. Please help me.
Attaching an entity to a DbContext, mark the attached entity and all its dependencies (i.e. associated entities) UnChanged. So its you who must tell EF what entities are new and what entities were modified.

Automatically add relationships for complex types

I'm looking to do bulk importing of complex models containing objects and collections into Neo4j.
I have the following model:
public class PSNGame
{
public int EarnedPlatinum { get; set; }
public int EarnedGold { get; set; }
public int EarnedSilver { get; set; }
public int EarnedBronze { get; set; }
public int EarnedTotal { get; set; }
public int AvailablePlatinum { get; set; }
public int AvailableGold { get; set; }
public int AvailableSilver { get; set; }
public int AvailableBronze { get; set; }
public int AvailableTotal { get; set; }
public double PercentCompleteBronze { get; set; }
public double PercentCompleteSilver { get; set; }
public double PercentCompleteGold { get; set; }
public double PercentCompletePlatinum { get; set; }
public double PercentCompleteTotal { get; set; }
public DateTimeOffset LastUpdated { get; set; }
public string Platform { get; set; }
public string NPCOMMID { get; set; }
public string TitleName { get; set; }
public string TitleDetail { get; set; }
public string Image { get; set; }
public string LargeImage { get; set; }
// complex model parts
public GameInfo GameInfo { get; set; }
public GameCommon.Rating Rating { get; set; }
public IEnumerable<GameCommon.RatingDescriptor> RatingDescriptors { get; set; }
public IEnumerable<GameCommon.Genre> Genres { get; set; }
public IEnumerable<GameCommon.Publisher> Publishers { get; set; }
public IEnumerable<GameCommon.Developer> Developers { get; set; }
public PSNGame()
{
}
}
I use this code to insert the games to Neo4j, however, it only works without the complex objects/collections:
var client = new GraphClient(new Uri("http://localhost:7474/db/data"));
client.Connect();
client.Cypher
.Match("(p:PSNProfile {PSNId : {profile}.PSNId})")
.ForEach(#"(game in {PSNGames} |
MERGE p-[:PLAYS {LastPlayed : game.LastUpdated}]->(g:PSNGame {NPCOMMID : game.NPCOMMID})-[:LOCALE]->(l:PSNGameLocalized {NPCOMMID : game.NPCOMMID})
SET g = game,
l = { NPCOMMID : game.NPCOMMID,
TitleName : game.TitleName,
TitleDetail : game.TitleDetail,
Locale : {locale}
})")
.WithParams(new
{
PSNGames = games.ToList(),
locale = locale,
profile = profile
})
.ExecuteWithoutResults();
I've tried doing nested FOREACH clauses, but this can get messy very fast. Also, the syntax of MERGE g-[:GAME_RATING]->g.Rating doesn't seem quite right and Neo4j complains that there is an invalid . token. My thought was to loop over the collections and access specific properties with the . accessor, but it doesn't look like Cypher likes the syntax.
For complex types, I would like to automatically create/update relationships/nodes for any child objects/collections contained in the complex type. Is there a way to do this in Neo4jClient?
Is there a way to do this in Neo4jClient?
No. Neo4jClient is a lower level driver, kind of like SqlClient. If you want more ORM-style behaviours on top of it, that would be a higher level library, equivalent to something like Entity Framework. There was a project called Neo4jRepository for a while, which built on top of Neo4jClient, but it has not been updated for the Neo4j 2.0 wave as far as I'm aware.

Join two Models to display in webpage

I'm building an application using ASP.NET MVC4 with code first data migrations. I have an estimates model, a clients model, a DbContext, and a view model I created. I am wanting to display the company name in a drop down, with the company name tied to an estimate. I have a ClientId in both models. I also created a DbSet<> and that didn't work either when querying against it.
I tried to create a viewmodel that I thought I could simply query against and display through my controller. I'm not having any luck in getting this to work. After a day plus of looking on here and other places, I'm out of ideas.
How can I query/join the two models, or query the viewmodel to get the company name associated with the clientId? Thanks for the help.
Models:
public class Estimates
{
[Key]
public int EstimateId { get; set; }
public int ClientId { get; set; }
public decimal EstimateAmount { get; set; }
[DisplayFormat(ApplyFormatInEditMode = true, DataFormatString = "{0:MM/dd/yyyy}")]
public DateTime EstimateDate { get; set; }
public string EstimateNotes { get; set; }
}
public class Clients
{
[Key]
public int ClientId { get; set; }
public string CompanyName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Phone { get; set; }
public string Email { get; set; }
public string Address { get; set; }
public string City { get; set; }
public string State { get; set; }
public string Zip { get; set; }
public ICollection<Estimates> Estimates { get; set; }
public ICollection<Contracts> Contracts { get; set; }
}
public class ClientEstimateViewModel
{
public Clients Clients { get; set; }
public Estimates Estimates { get; set; }
}
public class NovaDb : DbContext
{
public NovaDb(): base("DefaultConnection")
{
}
public DbSet<Clients> Clients { get; set; }
public DbSet<Estimates> Estimates { get; set; }
public DbSet<Contracts> Contracts { get; set; }
public DbSet<Invoices> Invoices { get; set; }
public DbSet<ClientEstimateViewModel> ClientViewModels { get; set; }
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
}
}
Controller:
NovaDb _db = new NovaDb();
ClientEstimateViewModel ce = new ClientEstimateViewModel();
public ActionResult Index()
{
var model =
(from r in ce.Clients
join x in ce.Estimates
where
//var model =
// from r in _db.Clients
// orderby r.CompanyName ascending
// select r;
return View(model);
}
Because you've created the relationship between client & estimate in your models, you should be able to create a query like this:
var query = from c in _db.clients
select new ClientEstimateViewModel
{
Clients = c,
Estimates = c.Estimates
}
Although you'd have to change your model so Estimates was public List<Estimates> Estimates { get; set; }
This would give you a collection of ClientEstimateViewModel which you could then pass to your view

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()
}
}
...
}

Resources