EF Core self joined ICollection query - sql-server

I have a problem with querying data from a self reference datatable having an ICollection.
Here are my table structures:
public class SoqHeading
{
public int Id { get; set; }
public string ItemNo { get; set; }
public string Heading { get; set; }
public SoqRevision SoqRevision_NP { get; set; }
public ICollection<SoqItem> Items { get; set; }
public int? ParentSoqHeadingId { get; set; }
public SoqHeading Parent_NP { get; set; }
public ICollection<SoqHeading> Children_NP { get; set; }
}
public class SoqItem
{
public int Id { get; set; }
public SoqPreliminaryOrContract_enum PreliminaryOrContract { get; set; }
public int SoqHeadingId { get; set; }
public SoqHeading SoqHeading_NP { get; set; }
}
I have a self referenced relation in the SoqHeading table which is 1 to many. The SoqHeading table can have zero or many SoqItems.
This is how the data is in my database
what i want is to query all from the root node of the SoqHeading table with its children and the items.
like this
{
"ItemNo": "C",
"Items": [
{
"ItemNo": "c-1",
},
{
"ItemNo": "c-2",
}
],
"Children_NP": [
{
"ItemNo": "C.1",
"Children_NP": [
{
"ItemNo": "C.1.1",
"Items": [
{
"ItemNo": "c.1.1-1",
},
{
"ItemNo": "c.1.1-2",
}
],
"Children_NP": [],
},
{
"ItemNo": "C.1.2",
"Items": [
{
"ItemNo": "c.1.2-1",
},
{
"ItemNo": "c.1.2-2",
}
],
"Children_NP": [],
}
],
},
{
"ItemNo": "C.2",
"Children_NP": [],
}
]
}
But currently i get data from the query like this
[
{
"ItemNo": "C"
},
{
"ItemNo": "C.1.2",
}
]
where C.1.2 has to be inside C, but it not. C and C.1.2 are in the same level which i dont wont to have produced by the following query
var entity = await _context.SoqHeadings
.Include(i=>i.Items)
.Include(i => i.Children_NP)
.Where(w => w.SoqRevision_NP.ProjectId == 10)
.ToListAsync();
please help

so it seems to be EFcore has no support to included the children on the first child node https://github.com/dotnet/efcore/issues/14144
so the work around is something like this here https://khalidabuhakmeh.com/recursive-data-with-entity-framework-core-and-sql-server

Related

Getting related data in .Net Core 3.1

I am trying to get related data from 2 tables. I am using .NET Core 3.1, EF Core, and the code-first approach. What I want is to pass a customerid (which is a foreign key in the order table) to get all the orders of that customer. I get some related output but I don't know how to get specific output.
I have commented out the .ThenInclude because it causes an error:
Lambda expression is not valid
Customer model class:
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace CRUDRelationship.Models
{
public class Customer
{
[Key]
public int CustomerId { get; set; }
public string Name { get; set; }
public string Email { get; set; }
//public List<Order> Order { get; set; }
}
}
Order model class:
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
namespace CRUDRelationship.Models
{
public class Order
{
[Key]
public int OrderId { get; set; }
public int Total { get; set; }
[ForeignKey("Customer")]
public int CustomerId { get; set; }
public Customer customer { get; set; }
}
}
Interface:
using CRUDRelationship.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace CRUDRelationship.Data
{
public interface ICustomerData
{
List<Customer> GetCustomers();
Customer GetCustomer(int id);
Customer AddCustomer(Customer customer);
List<Order> GetOrderByCustomer(int CustomerId);
Order AddOrder(Order order);
}
}
Implementation:
using CRUDRelationship.Models;
using Microsoft.EntityFrameworkCore;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace CRUDRelationship.Data
{
public class CustomerData : ICustomerData
{
private InvetoryContext _invetoryContext;
public CustomerData(InvetoryContext invetoryContext)
{
_invetoryContext = invetoryContext;
}
public Customer AddCustomer(Customer customer)
{
_invetoryContext.Customers.Add(customer);
_invetoryContext.SaveChanges();
return customer;
}
public Order AddOrder(Order order)
{
_invetoryContext.Orders.Add(order);
_invetoryContext.SaveChanges();
return order;
}
public Customer GetCustomer(int id)
{
throw new System.NotImplementedException();
}
public List<Customer> GetCustomers()
{
return _invetoryContext.Customers.ToList();
}
public List<Order> GetOrderByCustomer(int CustomerId)
{
return _invetoryContext.Orders
.Include(order => order.customer)
//.ThenInclude(customer => customer.Name)
.Where(order => order.CustomerId == CustomerId).ToList();
}
}
}
Customer table:
Order table:
Output I get when I pass customer id 2:
[
{
"orderId": 2,
"total": 200,
"customerId": 2,
"customer": {
"customerId": 2,
"name": "Ankit",
"email": "ankit#gmail.com"
}
},
{
"orderId": 4,
"total": 15000,
"customerId": 2,
"customer": {
"customerId": 2,
"name": "Ankit",
"email": "ankit#gmail.com"
}
}
]
This is the output I want:
{
"customer": {
"customerId": 2,
"name": "Ankit",
"email": "ankit#gmail.com",
"Order": [
{
"orderId": 2,
"total": 200,
"customerId": 2
},
{
"orderId": 4,
"total": 15000,
"customerId": 2
}
]
}
}

EF return columns data as list or array

I have two tables, which have following foreign key
Poll(CreatedBy) --> CreateBy(ID)
On performing join, I am getting data as following:
I want to write an query using EF (if possible) to return result as:
[{
"id": 1,
"users": [
{
"email": "abc.com"
}
]
},
{
"id": 3,
"users": [
{
"email": "xyz.test"
},
{
"email": "tet.com"
}
]
}]
Assuming that the class structure like below:
public class Poll
{
public int ID { get; set; }
public string Name { get; set; }
public List<CreateBy> CreateBy { get; set; }
}
public class CreateBy
{
public int ID { get; set; }
public string EmailAddress { get; set; }
public string DisplayName { get; set; }
[ForeignKey("Poll")]
public int PollId { get; set; }
}
Data source:
Linq query:
var result = (from p in _context.Poll.ToList()
join c in _context.CreateBy on p.ID equals c.PollId
group p by p.ID into g
select new
{
id = g.Key,
users = g.Select(x => x.CreateBy.Where(z => z.PollId == g.Key).Select(y => new { email = y.EmailAddress })).FirstOrDefault()
}).ToList();
Result:

How insert new array into existing embedded array in C#?

I have a little bit problem with an data update in mongoDB. I have an array embedded in an other array who is embedded in a document (yaaaaay ^^). So my collection is like that :
{
"_id" : ObjectId("5965e0b4f1042c4c3f1d8edc"),
"Builder" : "Google",
"Family" : "Car",
"ProductName" : "ABCD_80A_PU170017",
"ProductNumber" : "N 1",
"Test" : [
{
"Num_Test" : "PU170017",
"Date_Start" : ISODate("2017-07-12T00:00:00.000Z"),
"Bench": [
{
"Room": 1,
"Num" : 1,
"Designation" : "AC1; AC3",
"IP" : "123.456.78.9",
"Capacity" : 12,
}
],
"User" : [
{
"Number" : "EBBW396",
"Password" : "titi",
"Name" : "NDJO",
"Surname" : "Charles",
"Tel" : "06XXXXXX",
"isAdmin" : true
}
]
}
]
}
And i want to insert a new array embedded in "Test".
So i found my happiness here : https://docs.mongodb.com/getting-started/csharp/update/ AND How to use C# to insert document into existing embedded documents?
And i have write this code :
static void Main(string[] args)
{
IMongoClient client = new MongoClient("mongodb://10.194.157.199:27017");
IMongoDatabase database = client.GetDatabase("PINEA");
IMongoCollection<Product> collection = database.GetCollection<Product>("Product");
var filter = Builders<Product>.Filter.Eq("Test.Num_Test", "PU170017");
var meter = new Meter();
meter.Value= 12;
meter.Date = DateTime.Now;
var meterList = new List<Meter>();
meterList.Add(meter);
var update = Builders<Product>.Update.Push("Result", new Result
{
MeterList = meterList
});
var result = collection.UpdateOne(filter, update);
}
But nothing happens, nothing has added or modified. I miss something important but i don't understand what is it.
Finally, here are my classes:
class Result
{
public List<Meter> MeterList { get; set; }
public List<Problem> Problem { get; set; }
}
class Meter
{
public int? Value { get; set; }
public DateTime? Date { get; set; }
}
class Test
{
public string Num_Test { get; set; }
public DateTime? Date_Start { get; set; }
public List<Bench> Bench { get; set; }
public List<User> User { get; set; }
public List<Result> Result { get; set; }
}
class Product
{
public string Builder { get; set; }
public string Fammily { get; set; }
public string ProductName { get; set; }
public string ProductNumber { get; set; }
public List<Test> Test { get; set; }
}
To explain the context, I need to update the array "result" regularly and maintain data arborescence like that. After the end of the test, data aren't modify anymore.
PS : I'm still a student but I work part time
Thanks

Post an array of complex objects with JSON, MVC model is do not bind

here is my codes.
json_model
var mix = {
MixName: $("#mixname").val(),
MixDesc: tinyMCE.activeEditor.getContent(),
Price: $("#price").val(),
DiseaseMixs: [],
MixProducts: []
}
Add items to DiseaseMixs and MixProducts
$("#DiseaseList").find("tbody tr").each(function (index) {
mix.DiseaseMixs.push({
MixID: parseInt(MixID),
DiseaseID: parseInt($(".diseaseid").eq(index).html()),
ImpactDegree: parseInt($(".derece option:selected").eq(index).html()),
Description: $(".diseaseMixDesc input").eq(index).val()
});
})
$("#productList").find("tbody tr").each(function (index) {
mix.MixProducts.push({
MixID: parseInt(MixID),
ProductID: parseInt($(".productid").eq(index).html()),
MeasureTypeID: parseInt($(".birim option:selected").eq(index).val()),
MeasureAmount: $(".measureAmount input").eq(index).val()
});
})
and end of this process, here is a sample json object that is post.
{
"MixName": "asdasddas",
"MixDesc": "<p>sadasd</p>",
"Price": "123",
"DiseaseMixs": [{
"MixID": 1,
"DiseaseID": 2,
"ImpactDegree": 5,
"Description": "asads"
}, {
"MixID": 1,
"DiseaseID": 3,
"ImpactDegree": 4,
"Description": "aqqq"
}],
"MixProducts": [{
"MixID": 1,
"ProductID": 2,
"MeasureTypeID": 3,
"MeasureAmount": "3"
}, {
"MixID": 1,
"ProductID": 3,
"MeasureTypeID": 2,
"MeasureAmount": "45"
}]
}
ajax post
$.ajax({
url: 'SaveMix',
type: 'POST',
data: JSON.stringify(mix),
contentType: 'application/json; charset=utf-8',
success: function (result) {
console.log(result);
},
error: function (xhr, status) {
alert(status);
console.log(xhr);
}
})
and MVC Model and JSONResult function
Model
public class MixModel
{
public string MixName { get; set; }
public string MixDesc { get; set; }
public float Price { get; set; }
DiseaseMix[] DiseaseMixs { get; set; } //DiseaseMix EntityFramework entity
MixProduct[] MixProducts { get; set; } //MixProduct EF
}
function
[HttpPost]
public JsonResult SaveMix(MixModel mix)
{
bool result = false;
//do something
return Json(new { result = result }, JsonRequestBehavior.AllowGet);
}
and here is the result I get is.
No matter how I tried, I could not bind the model.
What am I doing wrong? Please give me some help.
Thanks in advance.
Model binding is failing because those 2 properties are currently private(which is the default when you don't specify anything explicitly).
Change the 2 properties to public so that model binder can set the values of those.
public class MixModel
{
public string MixName { get; set; }
public string MixDesc { get; set; }
public float Price { get; set; }
public DiseaseMix[] DiseaseMixs { get; set; } //DiseaseMix EntityFramework entity
public MixProduct[] MixProducts { get; set; } //MixProduct EF
}
I also suggests to not mix your view models with entities generated by your ORM. That creates a tightly coupled solution.

Nancy with Complex object using JSON not working

Client code:
var basket = {
products: [],
user: { name: "schugh" }
};
$("#basket table tr").each(function (index, item) {
var product = $(item).data('product');
if (product) {
basket.products.push(product);
}
});
$.ajax({
url: "http://localhost:12116/basketrequest/1",
async: true,
cache: false,
type: 'POST',
data: JSON.stringify(basket),
contentType: 'application/json; charset=utf-8',
dataType: 'json',
success: function (result) {
alert(result);
},
error: function (jqXHR, exception) {
alert(exception);
}
});
Server code:
Post["/basketrequest/{id}"] = parameters =>
{
var basketRequest = this.Bind(); //basketrequest is null
return Response.AsJson(basketRequest , HttpStatusCode.OK);
};
Other model classes:
[Serializable]
public class BasketRequest
{
public User User;
public List<Product> Products;
}
public class Product
{
public int Id { get; set; }
public string Name { get; set; }
public string Category { get; set; }
public decimal Price { get; set; }
public ProductStatus ProductStatus { get; set; }
}
public enum ProductStatus
{
Created,
CheckedBy,
Published
}
public class User
{
public string Name { get; set; }
}
The code in the Nancy Module this.Bind(); returns null. If I change the Complex object to just List<Product>, i.e. with no wrapper BasketRequest, the object is fine...
Any pointers?
EDIT: JSON posted:
{
"User": {
"Name": "SChugh"
},
"Products": [{
"Id": 1,
"Name": "Tomato Soup",
"Category": "Groceries",
"Price": 1
}, {
"Id": 2,
"Name": "Yo-yo",
"Category": "Toys",
"Price": 3.75
}]
}
Your BasketRequest object should implement properties instead of fields. So
public class BasketRequest
{
public User User { get; set; }
public List<Product> Products { get; set; }
}
also you should probably use the generic method too
this.Bind<BasketRequest>();

Resources