Breeze query on related properties not working? - breeze

From the Breeze document this should be working, but I can't make it work for me.
This is my EF code first classes:
public class Company
{
public int Id { get; set; }
public int? SectorId { get; set; }
public Sector Sector { get; set; }
}
public class Sector
{
public int Id { get; set; }
public string Name { get; set; }
}
In Breeze controller:
[HttpGet]
public IQueryable<Company> Companies()
{
return _repository.Context.Companies.Include("Sector");
}
I want to make a query like this:
var query = breeze.EntityQuery.from("Companies").where("Sector.Name", "==", "Finance");
or
var query = breeze.EntityQuery.from("Companies").where("Sector", "any", "Name", "==", "Finance");
But I get this error:
unable to locate property: Sector on type: Company
If I change to lower case,
var query = breeze.EntityQuery.from("Companies").where("sector.name", "==", "Finance");
or
var query = breeze.EntityQuery.from("Companies").where("sector", "any", "name", "==", "Finance");
I got this error:
undefined is not a function
What's my problem? I'm using Breeze v.1.4.14.

Try this query in your Linq:
[HttpGet]
public IQueryable<dynamic> Companies()
{
return _repository.Context.Companies.Select(a=>new
{
Company=a,
Sector=a.Sector
});
}
You missed the constructor in your entity now you can check it
Sector entity:
public class Sector {
public sector(){
Companies=new Hashest<Company >();
}
public virtual ICollection<Company> Companies {get;set;}
}

Related

Mapster - mapping descendant classes from base class

Classes:
public class Department
{
public string Name { get; set; }
}
public class DepartmentA : Department
{
public string NameA { get; set; }
}
public class Employee
{
public string Name { get; set; }
public int Salary { get; set; }
public string Address { get; set; }
public Department Department { get; set; }
}
public class EmployeeDTO
{
public string Name { get; set; }
public int Salary { get; set; }
public string Address { get; set; }
public Department Department { get; set; }
}
Code:
DepartmentA departmentA = new DepartmentA { NameA = "depA", Name = "dep" };
Employee emp = new Employee
{
Name = "James",
Salary = 20000,
Address = "London",
Department = departmentA
};
//Mapster
var empDTO = emp.Adapt<EmployeeDTO>();
//AutoMapper
//var config = new MapperConfiguration(cfg => cfg.CreateMap<Employee, EmployeeDTO>());
//var mapper = config.CreateMapper();
//EmployeeDTO empDTO = mapper.Map<EmployeeDTO>(emp);
Console.WriteLine("SourceType:" + emp.Department.GetType().Name);
Console.WriteLine("DestType:" + empDTO.Department.GetType().Name);
If you run the code you will see that SourceType and DestType are not the same. How do I achieve that they are the same? Mapster mapps department as Department class (ancestor) and not as DepartmentA class (descendant).
In this example I know that there is descendant in emp.Department but in my app I won't know. So the solution of this problem must be generic.
I tried to solve this problem in AutoMapper. Got the same results. As #Prolog wrote below, in AutoMapper is working. I updated main code. I am still interested if someone solved issue in Mapster.
You need to use ShallowCopyForSameType, AutoMapper will perform deep copy only declared types, Mapster perform deep copy for all types.

The entity type <type> is not part of the model from the current context

I get this error (An exception of type 'System.InvalidOperationException' occurred in EntityFramework.dll but was not handled in user code
The entity type tblMessage is not part of the model for the current context.) and have tried fixes I found online but they didnt seem to help. I also did somethin similar for another database tabel earlier in the code.
Im trying to retrieve messages form my database table called tblMessages.
Constructor:
public JsonResult ConversationWithContact(int contact)
{
if (Session["UserID"] == null)
{
return Json(new {status = "error", message = "User is not logged in"});
}
//var currentUser = (Models.tblUser)Session["UserID"];
var conversations = new List<Models.tblMessage>();
using (var db = new Models.ChatContext())
{
int currentUserId = (int)Session["UserID"];
var currentUser = db.Users.FirstOrDefault(x => x.Id == currentUserId);
conversations = db.Conversations.Where(c => (c.receiverId == currentUser.Id
&& c.senderId == contact) ||
(c.receiverId == contact
&& c.senderId == currentUser.Id))
.OrderBy(c => c.created_at)
.ToList();
}
return Json(
new {status = "success", data = conversations},
JsonRequestBehavior.AllowGet
);
}
Context:
public ChatContext() : base("TrinityEntities")
{
}
public static ChatContext Create()
{
return new ChatContext();
}
public DbSet<tblUser> Users { get; set; }
public DbSet<tblMessage> Conversations { get; set; }
Database model class:
public class tblMessage
{
public tblMessage()
{
status = messageStatus.Sent;
}
public enum messageStatus
{
Sent,
Delivered
}
public int Id { get; set; }
public int senderId { get; set; }
public int receiverId { get; set; }
public string message { get; set; }
public messageStatus status { get; set; }
public System.DateTime created_at { get; set; }
}
Here is issue with Table Mapping to database. each entity will be set up to map to a table with the same name as the DbSet<TEntity> property that exposes to the derived context. If no DbSet<TEntity> is included for the given entity, the class name is used.
as you set in your code Users and Conversations is not table name. for that you can customize also refere https://learn.microsoft.com/en-us/ef/core/modeling/relational/tables
and use Data Annotations for specify table name.
public messageStatus status { get; set; }
i think this property is not not part of your table column so you have to specify [NotMapped] Data Annotations.
after changes and adding Data Annotations to table context and table look likes.
public class ChatContext : DbContext
{
public ChatContext()
{
}
public virtual DbSet<tblUser> Users { get; set; }
public virtual DbSet<tblMessage> Conversations { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
if (!optionsBuilder.IsConfigured)
{
optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=test;Trusted_Connection=True;MultipleActiveResultSets=true");
}
}
}
and your models(tables) entities look like.
[Table("tblMessage")]
public class tblMessage
{
public tblMessage()
{
status = messageStatus.Sent;
}
public enum messageStatus
{
Sent,
Delivered
}
public int Id { get; set; }
public int senderId { get; set; }
public int receiverId { get; set; }
public string message { get; set; }
[NotMapped]
public messageStatus status { get; set; }
public System.DateTime created_at { get; set; }
}
[Table("tblUser")]
public class tblUser
{
public int id { get; set; }
public string name { get; set; }
}
now you can access your Conversations and Users after adding [Table("<table-name>")] Data-Annotations.
also you can use Fluent API for table mapping.
after using table mapping table after debug code image like.
i hope it helps you and let me know if require any more information. :)

Update existing entity framework with database (by adding new tables from db)

Hi i have an entity and i am gonna add two tables from database named as country and state.
There is a relation between these two tables based on CountryId.
I used the "Update Model from database ..." to add these two entity types.
I have manually written two classes for these two entity-types given as below:-
public partial class Country
{
//[Key] //[DatabaseGenerated(System.ComponentModel.DataAnnotations.Schema.DatabaseGeneratedOption.Identity)]
public int CountryID { get; set; }
public string CountryName { get; set; }
}
public partial class State
{
public int StateID { get; set; }
public string StateName { get; set; }
public int CountryID { get; set; }
}
public DbSet<Country> Countries { get; set; }
public DbSet<State> States { get; set; }
Controller to fetch coutries and states :-
public JsonResult GetCountries()
{
List<Country> allCountry = new List<Country>();
using (SunilEntities dc = new SunilEntities())
{
allCountry = dc.Countries.OrderBy(a => a.CountryName).ToList();
}
return new JsonResult { Data = allCountry, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
public JsonResult GetStates(int countryID)
{
List<State> allState = new List<State>();
using (SunilEntities dc = new SunilEntities())
{
allState = dc.States.Where(a => a.CountryID.Equals(countryID)).OrderBy(a => a.StateName).ToList();
}
return new JsonResult { Data = allState, JsonRequestBehavior = JsonRequestBehavior.AllowGet };
}
But I am getting an error "The entity type Country is not part of the model for the current context".
What should be the exact classes to be used to use these two tables in my controller?
Is there any way I can get automated classes after entity being updated with newer tables?
Under your yourmodel.edmx file there is yourmodel.tt and it generates relevant classes, thus there is no need to write these classes. By using relevant namespace you can use them.
I got the solution change models as below:-
public partial class Country
{
public Country()
{
this.States = new HashSet<State>();
}
public int CountryID { get; set; }
public string CountryName { get; set; }
public virtual ICollection<State> States { get; set; }
}
public partial class State
{
public int StateID { get; set; }
public string StateName { get; set; }
public Nullable<int> CountryID { get; set; }
public virtual Country Country { get; set; }
public virtual State State1 { get; set; }
public virtual State State2 { get; set; }
}
and change controller as given below:-
public JsonResult GetCountries()
{
using (SunilEntities dc = new SunilEntities())
{
var ret = dc.Countries.Select(x => new { x.CountryID, x.CountryName }).ToList();
return Json(ret, JsonRequestBehavior.AllowGet);
}
}
// Fetch State by Country ID
public JsonResult GetStates(int countryID)
{
using (SunilEntities dc = new SunilEntities())
{
var ret = dc.States.Where(x => x.CountryID == countryID).Select(x => new { x.StateID, x.StateName }).ToList();
return Json(ret, JsonRequestBehavior.AllowGet);
}
}

MVC 4: building composite viewmodel

I am new to ASP.NET MVC. I need to build a composite viewmodel out of three nested or cascading classes: Sport>Tournament>TournamentEvent
public class Sport
{
public int Id { get; set; }
public string SportName { get; set; }
public virtual ICollection<Tournament> Tournaments { get; set; }
}
public class Tournament
{
public int Id { get; set; }
public string TournamentName { get; set; }
public int SportId { get; set; }
public virtual ICollection<TournamentEvent> TournamentEvents { get; set; }
}
public class TournamentEvent
{
public int Id { get; set; }
public string EventName { get; set; }
public int TournamentId { get; set; }
}
As you can gather, each sport contains a collection of tournaments and each tournament contains a collection of events. I need to construct an unordered list, like so:
<li> Soccer
<li>English Premier League
<li>Chelsea v Arsenal</li>
</li>
</li>
I need to build a composite viewmodel, using linq, to pass to my view, but I just can't figure it out. Please help
Don't you just need a parent vie model that contains a list of Sport?
public class Sport
{
public List<Sport> Sports { get; set; }
}
You can iterate through the collections using razor.
Can you clarify where you think linq comes into it? I might have got the wrong end of the stick.
I don't think that works, tom. I need access to the Tournament and TournamentEvent classes and I need to load them into my object, which is where linq comes in. In the SportsController:
public partial class SportsController : Controller
{
private MyDb db = new MyDb();
public virtual ActionResult Index()
{
var menuObject = from s in db.Sports
select s;
return View(menuObject);
}
}
Create a class call it SportTournamentEventViewModel.cs
using "LibraryName".Models;
public class SportTournamentEventViewModel
{
public List<Sport> Sports {get;set;}
public List<Tournament> Tournaments {get;set;}
public List<TournamentEvent> Events {get;set;}
}
in your action
private NameOfEntities db = new NameOfEntities();
public ActionResult "ActionResultName"()
{
db.Configuration.LazyLoading = false;
var sportList = db.Sport.ToList();
var tournamentList = db.Tournament.ToList();
var eventList = db.TournamentEvents.ToList();
var viewModel = new SportTournamentViewModel
{
Sports = sportList,
Tournaments = tournamentList,
Events = eventList,
};
return View(viewModel);
}

Populating a linking table in a many-to-many relationship

I am trying to get to grips with EF4 CTP5. I have two classes that have a many-to-many relationship: Member and MemberGroup. CTP5 Code First generated two tables (Members and MemberGroups) and also a third named MemberGroupMembers that has two columns (MemberGroupId and MemberId) So far everything is as I was expecting it to be. I have seeded the database with some Members and MemberGroups. The problem is that I cannot find how to assign one or more MemberGroups to a Member, which would result in inserting a row into the MemberGroupMembers table for each MemberGroup that the Member is assigned to.
public class Member
{
public int Id { get; set; }
public Guid SecureId { get; set; }
public DateTime JoinedOn { get; set; }
public virtual ICollection<MemberGroup> MemberGroups { get; set; }
}
public class MemberGroup
{
public int Id { get; set; }
public string Name { get; set; }
public DateTime CreatedOn { get; set; }
public virtual ICollection<Member> Members { get; set; }
}
public class CTP5testContext : DbContext
{
public CTP5testContext() : base("CTP5test") { }
public DbSet<Member> Members { get; set; }
public DbSet<MemberGroup> MemberGroups { get; set; }
}
public class CTP5testContextInitializer : DropCreateDatabaseIfModelChanges<CTP5testContext>
{
protected override void Seed(CTP5testContext context)
{
new List<Member>
{
new Member
{
Id = 1,
SecureId = Guid.NewGuid(),
JoinedOn = DateTime.Now
}
,
new Member
{
Id = 2,
SecureId = Guid.NewGuid(),
JoinedOn = DateTime.Now
}
}.ForEach(m => context.Members.Add(m));
var memberGroup = new MemberGroup()
{
Id = 1,
Name = "MemberGroup 1",
CreatedOn = DateTime.Now
};
context.MemberGroups.Add(memberGroup);
// How can I assign Member 1 to MemberGroup 1 ?????
context.SaveChanges();
}
}
I hope that it is clear what I am trying to do here and that someone can give me an example of how to achieve this.
Regards,
Erwin
You must use collections defined in your POCO classes. So if you want to assign member1 to memberGroup you will simply call:
memberGroup.Members.Add(member1);

Resources