I want to get a nested JSON reply with my EF query and not sure how to do this.
I have declared my Models as follows:
[Serializable]
public class StockReturnMethod
{
public int WarehouseID { get; set; }
public int ProductSKUID { get; set; }
public int LotID { get; set; }
public string LotName { get; set; }
public int AreaID { get; set; }
public string AreaName { get; set; }
public int BinID { get; set; }
public string BinName { get; set; }
public List<AvailibleStock> Stock { get; set; }
}
[Serializable]
public class AvailibleStock
{
public int WarehouseID { get; set; }
public int ProductSKUID { get; set; }
public string ProductSKUName { get; set; }
public string WarehouseName { get; set; }
public string Status { get; set; }
public int QtyUnassigned { get; set; }
}
Here is my EF query that I have so far.
{
return (from WH in SCMENT.Warehouses
join WL in SCMENT.WarehouseLots on WH.WarehouseID equals WL.WarehouseID
join WA in SCMENT.WarehouseAreas on WL.WarehouseLotID equals WA.WarehouseLotID
join WB in SCMENT.WarehouseBins on WA.WarehouseAreaID equals WB.WarehouseAreaID
join SLI in SCMENT.StockLineItems on WH.WarehouseID equals SLI.WarehouseID
join PSKU in SCMENT.ProductSKUs on SLI.ProductSKUID equals PSKU.ProductSKUID
where SLI.SystemAreaID == 1
select new StockReturnMethod()
{
WarehouseID = WH.WarehouseID,
LotID = WL.WarehouseLotID,
LotName = WL.WarehouseLotName,
AreaID = WA.WarehouseAreaID,
AreaName = WA.WarehouseAreaName,
BinID = WB.WarehouseBinID,
BinName = WB.WarehouseBinName,
ProductSKUID = PSKU.ProductSKUID,
Stock = (Will I create a sub query here?)
}
)
public List<AvailibleStock> Stock { get; set; }
Change this to:
public IList<AvailibleStock> Stock { get; set; }
Edit: Here's working sample from one of my projects that you can use as reference:
public class StatisticsModel
{
public int Id { get; set; }
public int ClientId { get; set; }
public int Opened { get; set; }
public IEnumerable<LocationsModel> Locations { get; set; }
}
public class LocationModel
{
public int Id { get; set; }
public string Name { get; set; }
public int OpenCount { get; set; }
}
return dbSet.Select(x => new StatisticsModel
{
Id = x.Id,
ClientId = x.ClientId,
Opened = x.OpenCount,
Locations = x.Locations.Select(z => new LocationsModel{
Id = z.Id,
Name = z.Store.Name,
OpenCount = z.OpenCount
})
})
Related
Hi there I've been banging my head now for two days and haven't been able to solve this one: I have this data structure:
[
{
"LocalObservationDateTime": "2019-12-12T19:50:00+02:00",
"EpochTime": 1576173000,
"WeatherText": "Thunderstorm",
"WeatherIcon": 15,
"HasPrecipitation": true,
"Reciprocation": "Rain",
"IsDayTime": false,
"Temperature": {
"Metric": {
"Value": 13.7,
"Unit": "C",
"UnitType": 17
},
"Imperial": {
"Value": 57,
"Unit": "F",
"UnitType": 18
}
}
}
]
I designed my data like this:
Table1:
Id,
LocalObservationDateTime,
EpochTime
WeatherText,
WeatherIcon,
HasPrecipitation,
PrecipitationType,
IsDayTime,
TemperatureId
Table2
TemperatureId,
ImperialId,
MetricId
Table3
Id,
Value,
Unit,
UnitType
I connected FKs tables 3 Id ImperialId and MetricId in Table 3 and TemperatureId in Table 2 to TemperatureId in table1
these are my models:
[Table("currentweather")]
public class CurrentWeather
{
[Key, Column("id")]
public int Id { get; set; }
[Column("locationid")]
public int LocationId { get; set; }
[Column("localobservationdatetime")]
public DateTime LocalObservationDateTime { get; set; }
[Column("epochtime")]
public long EpochTime { get; set; }
[Column("weathertext")]
public string WeatherText { get; set; }
[Column("weathericon")]
public int WeatherIcon { get; set; }
[Column("hasprecipitation")]
public bool HasPrecipitation { get; set; }
[Column("precipitationtype")]
public string PrecipitationType { get; set; }
[Column("isdaytime")]
public bool IsDayTime { get; set; }
[ForeignKey("Temperature")]
[Column("temperatureid")]
public int TemperatureId { get; set; }
[Column("mobilelink")]
public string MobileLink { get; set; }
[Column("link")]
public string Link { get; set; }
[NotMapped]
public Temperature Temperature { get; set; }
}
[Table("temperature")]
public class Temperature
{
[Key, Column("tepmeratureid")]
public int TemperatureId { get; set; }
[ForeignKey("Imperial")]
[Column("imperialid")]
public int ImperialId { get; set; }
[ForeignKey("Metric")]
[Column("metricid")]
public int MetricId { get; set; }
[NotMapped]
public CurrentWeather CurrentWeather { get; set; }
[NotMapped]
public TemperatureUnit Imperial { get; set; }
[NotMapped]
public TemperatureUnit Metric { get; set; }
}
public class TemperatureUnit
{
public double Value { get; set; }
public Unit Unit { get; set; }
public int UnitType { get; set; }
[NotMapped]
public Temperature Temperature { get; set; }
}
public enum Unit { C,F}
I am using Mysql and Net.core EF6
When adding data only table 1 gets the data but the other two don't HELP!!!
Your json object doesn't match your database tables, so you'll have to do some mapping of those properties.
Note: the below code leaves off several properties, but you should be able to follow this and add them in as needed.
First, you need to make your json string into an object. If passed in from a controller you can use model binding; otherwise you'll have to deserialize it. Here's an appropriate view model for that:
public class CurrentWeatherViewModel
{
public DateTime LocalObservartionTime { get; set; }
public int EpochTime { get; set; }
public string WeatherText { get; set; }
//additional props here
public TemperatureViewModel Temperature { get; set; }
}
public class TemperatureViewModel
{
public MetricViewModel Metric { get; set; }
public ImperialViewModel Imperial { get; set; }
}
public class MetricViewModel
{
public decimal Value { get; set; }
public string Unit { get; set; }
public int UnitType { get; set; }
}
public class ImperialViewModel
{
public decimal Value { get; set; }
public string Unit { get; set; }
public int UnitType { get; set; }
}
You can deserialize the json string into that object like this:
var jsonString = " {\"EpochTime\": 1576173000,\"WeatherText\": \"Thunderstorm\",\"WeatherIcon\": 15,\"HasPrecipitation\": true,\"Reciprocation\": \"Rain\",\"IsDayTime\": false,\"Temperature\": {\"Metric\": {\"Value\": 13.7,\"Unit\": \"C\",\"UnitType\": 17},\"Imperial\": {\"Value\": 57,\"Unit\": \"F\",\"UnitType\": 18}}}";
CurrentWeatherViewModel currentWeatherViewModel = Newtonsoft.Json.JsonConvert.DeserializeObject<CurrentWeatherViewModel>(jsonString);
Once it's deserialized into the viewmodel object, you can create your entities and save them to the db:
CurrentWeather currentWeather = new CurrentWeather
{
WeatherText = currentWeatherViewModel.WeatherText,
Temperature = new Temperature
{
Measurements = new Measurement[] {
new Measurement {
Unit = currentWeatherViewModel.Temperature.Metric.Unit,
UnitType = currentWeatherViewModel.Temperature.Metric.UnitType,
Value = currentWeatherViewModel.Temperature.Metric.Value,
},
new Measurement {
Unit = currentWeatherViewModel.Temperature.Imperial.Unit,
UnitType = currentWeatherViewModel.Temperature.Imperial.UnitType,
Value = currentWeatherViewModel.Temperature.Imperial.Value,
}
}
}
};
db.CurrentWeathers.Add(currentWeather);
db.SaveChanges();
Here's the entity classes:
public class CurrentWeather
{
public int Id { get; set; }
public DateTime? LocalObservartionTime { get; set; }
public int EpochTime { get; set; }
public string WeatherText { get; set; }
//additional props here
public virtual Temperature Temperature { get; set; }
}
public class Temperature
{
public int Id { get; set; }
//relationship
public int CurrentWeatherId { get; set; }
//relationship
public virtual ICollection<Measurement> Measurements { get; set; }
}
public class Measurement
{
public int Id { get; set; }
public decimal Value { get; set; }
public string Unit { get; set; }
public int UnitType { get; set; }
//relationship
public int TemperatureId { get; set; }
public virtual Temperature Temperature { get; set; }
}
I'm fairly new to the awesomeness that is JSON - I'm using the DataContractJsonSerializer. I cannot get the multiple instances of the Customer objects into the list.
The Attributes work as expected but there are no Customer objects in my List..??
{
"#attributes":
{"count":"2",
"offset":"0",
"limit":"100"
},
"Customer":
{
"firstName":"cust ",
"lastName":"one",
"title":"Owner",
"company":"CustOne Plants",
"companyRegistrationNumber":"",
"vatNumber":"",
"creditAccountID":"1",
"customerTypeID":"4",
"discountID":"0",
"taxCategoryID":"0",
"customerID":"1",
"createTime":"2017-06-19T23:36:11+00:00",
"timeStamp":"2017-06-20T18:55:11+00:00",
"archived":"false"
}
"Customer":
{
"firstName":"cust ",
"lastName":"two",
"title":"Owner",
"company":"CustTwo House of Games",
"companyRegistrationNumber":"",
"vatNumber":"",
"creditAccountID":"1",
"customerTypeID":"4",
"discountID":"0",
"taxCategoryID":"0",
"customerID":"1",
"createTime":"2017-06-19T23:36:11+00:00",
"timeStamp":"2017-06-20T18:55:11+00:00",
"archived":"false"
}
}
.NET code:
StreamReader stream = new StreamReader(#"C:\TMC Projects\PotteryManufacturing\CustomerJSON.txt");
string text = stream.ReadToEnd();
stream.Close();
byte[] byteArray = Encoding.UTF8.GetBytes(text);
MemoryStream stream1 = new MemoryStream(byteArray);
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(CustomersRoot));
var varInfo = serializer.ReadObject(stream1) as CustomersRoot;
stream1.Close();
and finally my classes/data contracts/data members:
[DataContract]
public class CustomersRoot
{
private List<Customer> m_Customers;
public CustomersRoot() { this.Customer = new List<Customer>(); }
[DataMember(Name ="#attributes")]
public Attributes attrs { get; set; }
[DataMember(Name = "Customer")]
public List<Customer> Customer
{
get { return m_Customers; }
set { m_Customers = value; }
}
}
[DataContract]
public class Customer
{
[DataMember(Name ="firstName")]
public string firstName { get; set; }
[DataMember(Name = "lastName")]
public string lastName { get; set; }
[DataMember(Name = "title")]
public string title { get; set; }
[DataMember(Name = "company")]
public string company { get; set; }
[DataMember(Name = "companyRegistrationNumber")]
public string companyRegistrationNumber { get; set; }
[DataMember(Name = "vatNumber")]
public string vatNumber { get; set; }
[DataMember(Name = "creditAccountID")]
public int creditAccountID { get; set; }
[DataMember(Name = "customerTypeID")]
public int customerTypeID { get; set; }
[DataMember(Name = "discountID")]
public int discountID { get; set; }
[DataMember(Name = "taxCategoryID")]
public int taxCategoryID { get; set; }
[DataMember(Name = "customerID")]
public int customerID { get; set; }
[DataMember(Name = "createTime")]
public string createTime { get; set; }
[DataMember(Name = "timeStamp")]
public string timeStamp { get; set; }
[DataMember(Name = "archived")]
public bool archived { get; set; }
}
[DataContract]
public class Attributes
{
[DataMember(Name = "count")]
public int count { get; set; }
[DataMember(Name = "offset")]
public int offset { get; set; }
[DataMember(Name = "limit")]
public int limit { get; set; }
}
I figured out what's going on here - the call can sometimes return an array of Customer objects (not formatted correctly above) OR a single instance of the object. When the web service returns a single Customer instance, the List code does not work. I will have to check on how to deal w/ this issue.
I have the following classes that I'm using to collect data and then return the structure in Json.
public class Outcome {
public int id { get; set; }
public string outcome { get; set; }
public string actionStep { get; set; }
public List<OutcomeActionResult> actionResults { get; set; }
public void setData(SqlDataReader reader, DateData dateData) {
this.id = Convert.ToInt32(reader["id"]);
this.outcome = Convert.ToString(reader["outcome"]);
this.actionStep = Convert.ToString(reader["action_step"]);
this.actionResults = new Outcomes().getActionResultByOutcomeId(this.id, dateData);
}
}
public class OutcomeActionResult {
public int id { get; set; }
public string actionResult { get; set; }
public ActionResultQuestion question { get; set; }
public void setData(SqlDataReader reader, DateData dateData) {
this.id = Convert.ToInt32(reader["id"]);
this.actionResult = Convert.ToString(reader["action_result"]);
this.question = new Outcomes().getActionResultQuestionByActionResultId(this.id, dateData);
}
}
public class ActionResultQuestion {
public int id { get; set; }
public string question { get; set; }
public bool isMultipleChoice { get; set; }
public List<MultipleChoiceOption> multipleChoiceOptions { get; set; }
ActionResultAnswer answer { get; set; }
public void setData(SqlDataReader reader, DateData dateData) {
this.id = Convert.ToInt32(reader["id"]);
this.question = Convert.ToString(reader["question"]);
this.isMultipleChoice = Convert.ToBoolean(reader["is_multi"]);
this.answer = new Outcomes().getActionResultAnswersByIdAndDate(this.id, dateData.year, dateData.month, dateData.day, dateData.shiftId);
}
}
public class ActionResultAnswer {
public int id { get; set; }
public string notes { get; set; }
public int employeeId { get; set; }
public int selectedAnswer { get; set; }
public string answer { get; set; }
public int year { get; set; }
public int month { get; set; }
public int day { get; set; }
public int shiftId { get; set; }
public void setData(SqlDataReader reader) {
this.id = Convert.ToInt32(reader["id"]);
this.notes = Convert.ToString(reader["notes"]);
this.employeeId = Convert.ToInt32(reader["employee_id"]);
this.selectedAnswer = reader.IsDBNull(reader.GetOrdinal("selected_answer")) ? -1 : Convert.ToInt32(reader["selected_answer"]);
this.answer = Convert.ToString(reader["answer"]);
this.year = Convert.ToInt32(reader["year"]);
this.month = Convert.ToInt32(reader["month"]);
this.shiftId = Convert.ToInt32(reader["shift_id"]);
}
}
As you can see, I have Outcome which contains a list of OutcomeActionResults each of which contains an ActionResultQuestion which has an ActionResultAnswer. Something like this:
Outcome -> List(OutcomeActionResult) --> ActionResultQuestion --> ActionResultAnswer
When I step through the code, all the data is being populated correctly and everything is fine. However, when I serialize the object structure to JSON it serializes everything except the ActionResultAnswer. Basically the deepest level of the structure gets chopped off. I've been unable to find anything that tells me why this is happening or how to have it not happen.
Probably ought to put the code that serializes the objects up here:
var response = outcomes.getOutcomesByClientAndDate(clientId, year, month, day, shiftId, dayOfWeek);
var json = JsonConvert.SerializeObject(response);
The answer property in your ActionResultQuestion class is not public. Therefore, it will not be serialized by Json.Net by default.
You can either make the property public...
public ActionResultAnswer answer { get; set; }
or, if you intend that it not be public, you can mark it with a [JsonProperty] attribute to allow the serializer to "see" it:
[JsonProperty]
ActionResultAnswer answer { get; set; }
I have two tables:
Companies
Contacts with a one-to-many relations (many contacts in one Company)
Contacts table EDITED:
public class Contact
{
public Guid Id { get; set; }
public DateTime dateCreated { get; set; }
public DateTime updated { get; set; }
public Boolean hidden { get; set; }
//Personal Data
public string title { get; set; }
public string jobTitle { get; set; }
public string firstName { get; set; }
public string lastName { get; set; }
public string department { get; set; }
public string email { get; set; }
public string logoUrl { get; set; }
public string personalRemarks { get; set; }
//Telephone list
public ICollection<Phone> Phones { get; set; }
//Addresses
public ICollection<Address> Addresses { get; set; }
//Bank Data
public ICollection<Bankdata> Bankdatas { get; set; }
//Tags
public ICollection<Tag> Tags { get; set; }
}
}
Companies table EDITED:
public class Organization
{
public Guid Id { get; set; }
public DateTime dateCreated { get; set; }
public DateTime dateUpdated { get; set; }
public Boolean hidden { get; set; }
//Company Data
public string organizationName { get; set; }
public string taxId { get; set; }
public string trades { get; set; }
public string organizationType { get; set; }
public string actionRadius { get; set; }
public string organizationRemarks { get; set; }
public string web { get; set; }
//Contacts
public ICollection<Contact> Contacts { get; set; }
//Tags
public ICollection<Tag> Tags { get; set; }
}
}
I have a method im my repository to select all the contacts in one company
public Organization GetOrganizationById(Guid Id)
{
return _context.Organizations
.Include(c => c.Contacts)
.Where(c => c.Id == Id)
.FirstOrDefault();
}
But since all I have is the company id I need to make a join between the two tables in order to get the name. Something like:
SELECT contacts,*, Organization.name
FROM contacts
INNER JOIN Organization ON Organization.id = Contacts.organization_id
WHERE Organization.id = id;
I have tried the following without success:
public Organization GetOrganizationById(Guid Id)
{
return _context.Organizations
.Include(o => o.organizationName)
.Include(c => c.Contacts)
.Where(c => c.Id == Id)
.FirstOrDefault();
}
Any help will be welcome
The right approach is to create a navigation property between the Organization class and the Contact class. The following code will let you understand the steps you need to do:
public class Contact
{
...
// Foreign key for Organization
public Guid OrganizationId { get; set; }
// Related Organization entity
[ForeignKey("OrganizationId ")]
public Organization Standard { get; set; }
}
public class Organization
{
...
// List of related Contacts
public virtual ICollection<Contact> Contacts { get; set; }
}
After creating a migration with this code you will implement your method as follows:
public Organization GetOrganizationById(Guid Id)
{
return _context.Organizations
.Include(c => c.Contacts)
.Where(c => c.Id == Id)
.FirstOrDefault();
}
Below are two tables that has a many to many relation and and also another table that has a relation with the two first. A mapping table is created by Visual Studio with the name OrderEmployee, but when I run the application and enter some information to the Timeunit create form, the mapping table OrderEmployee is empty!
Should there not be some IDs added to that table since it has a relation with the Timeunit table or how is this mapping table thing working, when will there be data added to the mapping table? Or is something wrong with my Entity Classes?
public class Order
{
public int ID { get; set; }
public string Name { get; set; }
public int? ManufacturerID { get; set; }
public virtual Manufacturer Manufacturer { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
}
public class Employee
{
public int ID { get; set; }
public string Name { get; set; }
public int EmployeeNumber { get; set; }
public virtual ICollection<Timeunit> Timeunits { get; set; }
public virtual ICollection<Order> Order { get; set; }
}
public class Timeunit
{
public int ID { get; set; }
public int Week { get; set; }
public int HoursPerWeek { get; set; }
public int EmployeeID { get; set; }
public int? OrderID { get; set; }
public virtual Employee Employee { get; set; }
public virtual Order Order { get; set; }
}
EDIT:
Create Method for Timeunit:
public ActionResult Create([Bind(Include = "ID,Week,HoursPerWeek,EmployeeID,OrderID")] Timeunit timeunit)
{
if (ModelState.IsValid)
{
db.Timeunits.Add(timeunit);
db.SaveChanges();
return RedirectToAction("Index");
}
ViewBag.ProjectID = new SelectList(db.Orders, "ID", "Name", timeunit.OrderID);
ViewBag.ResourceID = new SelectList(db.Employees, "ID", "Name", timeunit.EmployeeID);
return View(timeunit);
}