This question already has answers here:
How to Sort a List<T> by a property in the object
(23 answers)
Closed 4 years ago.
I have the following classes.
public class Response
{
List<Make> Makes { get; set; }
public Response()
{
this.Makes = new List<Make>();
}
}
public class Make
{
public string Name { get; set; }
public List<Agent> Agents { get; set; }
public Make()
{
this.Agents = new List<Agent>();
}
}
public class Agent
{
public int Id { get; set; }
public string Name { get; set; }
public List<Offer> Offers { get; set; }
public Agent()
{
this.Offers = new List<Offer>();
}
}
public class Offer
{
public int Id { get; set; }
public List<Model> Models { get; set; }
public Offer()
{
this.Models = new List<Model>();
}
}
public class Model
{
public string Name { get; set; }
public Price Price { get; set; }
public Model()
{
this.Price = new Price();
}
}
public class Price
{
public decimal Total { get; set; }
public decimal Vat { get; set; }
}
Using linq how can I get a list of Makes, that are ordered by the cheapest model first. Also, I want the models for each agent to be ordered by the cheapest first.
The easy way is to put the data into a flat object like a datatable and then sort :
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
namespace ConsoleApplication98
{
class Program
{
static void Main(string[] args)
{
Response response = new Response() {
Makes = new List<Make>() {
new Make() {
Name = "AAA", Agents = new List<Agent>() {
new Agent() {
Id = 123, Name = "SSS", Offers = new List<Offer>() {
new Offer() {
Id = 100, Models = new List<Model>() {
new Model() { Name = "TTT", Price = new Price() { Total = 1.0M, Vat = 2.0M}},
new Model() { Name = "UUU", Price = new Price() { Total = 2.0M, Vat = 3.0M}},
},
},
new Offer() {
Id = 200, Models = new List<Model>() {
new Model() { Name = "TTT", Price = new Price() { Total = 1.0M, Vat = 2.0M}},
new Model() { Name = "UUU", Price = new Price() { Total = 2.0M, Vat = 3.0M}}
}
}
}
},
new Agent() {
Id = 456, Name = "SST", Offers = new List<Offer>() {
new Offer() {
Id = 100, Models = new List<Model>() {
new Model() { Name = "TTT", Price = new Price() { Total = 1.0M, Vat = 2.0M}},
new Model() { Name = "UUU", Price = new Price() { Total = 2.0M, Vat = 3.0M}},
},
},
new Offer() {
Id = 200, Models = new List<Model>() {
new Model() { Name = "TTT", Price = new Price() { Total = 1.0M, Vat = 2.0M}},
new Model() { Name = "UUU", Price = new Price() { Total = 2.0M, Vat = 3.0M}}
}
}
}
}
}
},
new Make() {
Name = "AAB", Agents = new List<Agent>() {
new Agent() {
Id = 123, Name = "SSS", Offers = new List<Offer>() {
new Offer() {
Id = 100, Models = new List<Model>() {
new Model() { Name = "TTT", Price = new Price() { Total = 1.0M, Vat = 2.0M}},
new Model() { Name = "UUU", Price = new Price() { Total = 2.0M, Vat = 3.0M}},
},
},
new Offer() {
Id = 200, Models = new List<Model>() {
new Model() { Name = "TTT", Price = new Price() { Total = 1.0M, Vat = 2.0M}},
new Model() { Name = "UUU", Price = new Price() { Total = 2.0M, Vat = 3.0M}}
}
}
}
},
new Agent() {
Id = 456, Name = "SST", Offers = new List<Offer>() {
new Offer() {
Id = 100, Models = new List<Model>() {
new Model() { Name = "TTT", Price = new Price() { Total = 1.0M, Vat = 2.0M}},
new Model() { Name = "UUU", Price = new Price() { Total = 2.0M, Vat = 3.0M}},
},
},
new Offer() {
Id = 200, Models = new List<Model>() {
new Model() { Name = "TTT", Price = new Price() { Total = 1.0M, Vat = 2.0M}},
new Model() { Name = "UUU", Price = new Price() { Total = 2.0M, Vat = 3.0M}}
}
}
}
}
}
}
}
};
DataTable dt = new DataTable();
dt.Columns.Add("Make Name", typeof(string));
dt.Columns.Add("Agent ID", typeof(int));
dt.Columns.Add("Agent Name", typeof(string));
dt.Columns.Add("Offer ID", typeof(int));
dt.Columns.Add("Model Name", typeof(string));
dt.Columns.Add("Total", typeof(decimal));
dt.Columns.Add("Vat", typeof(decimal));
foreach (Make make in response.Makes)
{
string makeName = make.Name;
foreach (Agent agent in make.Agents)
{
int agentID = agent.Id;
string agentName = agent.Name;
foreach (Offer offer in agent.Offers)
{
int offerID = offer.Id;
foreach (Model model in offer.Models)
{
string modelName = model.Name;
decimal vat = model.Price.Vat;
decimal total = model.Price.Total;
dt.Rows.Add(new object[] {
makeName,
agentID,
agentName,
offerID,
modelName,
vat,
total
});
}
}
}
}
dt = dt.AsEnumerable().OrderBy(x => x.Field<decimal>("Total")).CopyToDataTable();
}
}
public class Response
{
public List<Make> Makes { get; set; }
public Response()
{
this.Makes = new List<Make>();
}
}
public class Make
{
public string Name { get; set; }
public List<Agent> Agents { get; set; }
public Make()
{
this.Agents = new List<Agent>();
}
}
public class Agent
{
public int Id { get; set; }
public string Name { get; set; }
public List<Offer> Offers { get; set; }
public Agent()
{
this.Offers = new List<Offer>();
}
}
public class Offer
{
public int Id { get; set; }
public List<Model> Models { get; set; }
public Offer()
{
this.Models = new List<Model>();
}
}
public class Model
{
public string Name { get; set; }
public Price Price { get; set; }
public Model()
{
this.Price = new Price();
}
}
public class Price
{
public decimal Total { get; set; }
public decimal Vat { get; set; }
}
}
It would be easier to verify if you'd provided sample values and the desired result, but here's my take on getting the Makes ordered using a LINQ one-liner:
response.Makes.OrderBy(
make => make.Agents.Select(
agent => agent.Offers.Min(
offer => offer.Models.OrderBy(model => model.Price.Total)
.First().Price.Total)));
Here's the flow (the inner bullets enable the outer bullets):
Get list of Makes
For each Make, select list of Agents
For each Agent, select the minimum offer
For each offer, order by the total price
Select the first (lowest) offer
For each Agent, the minimum offer is now selected
The makes can now be ordered by the minimum offer it contains
I'm not absolutely certain that the flow above makes sense, but give the implementation a shot!
Related
I have 2 models:
public class Office
{
[Key] public int OfficeId { get; set; }
public string Brand { get; set; }
public string Type { get; set; }
[NotMapped] public IRepository<CarItem> CarsDataBase { get; set; }
public virtual ICollection<CarItem> Cars { get; set; }
public Office(string brand, string type)
{
Type = type;
Cars = new List<CarItem>();
Brand = brand;
}
}
and
public class CarItem
{
public CarItem() { } //for serialization
public CarItem(string brand, string model, uint price, uint stockBalance)
{
Brand = brand;
Model = model;
Price = price;
StockBalance = stockBalance;
}
[Key] public int ItemId { get; set; }
public string Brand { get; set; }
public string Model { get; set; }
public uint Price { get; set; }
public uint StockBalance { get; set; }
public int? OfficeId { get; set; }
public Office Office { get; set; }
}
and DataBase Context
public class EFDataBaseContext : DbContext
{
public DbSet<Office> Offices => Set<Office>();
public DbSet<CarItem> CarItems => Set<CarItem>();
public EFDataBaseContext()
{
Database.EnsureCreated();
}
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
optionsBuilder.UseSqlServer("Server=(localdb)\\mssqllocaldb;Database=carstoredb;Trusted_Connection=True;");
}
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Office>().HasData
(
new Office("Audi", "SQL")
{
OfficeId = 1,
},
new Office("Scoda", "SQL")
{
OfficeId = 2,
}
);
modelBuilder.Entity<CarItem>(entity =>
{
entity.HasOne(item => item.Office).WithMany(office => office.Cars).HasForeignKey(item => item.OfficeId).OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity<SparePart>(entity =>
{
entity.HasOne(item => item.Office).WithMany(office => office.Parts).HasForeignKey(item => item.OfficeId).OnDelete(DeleteBehavior.Cascade);
});
modelBuilder.Entity<CarItem>().HasData
(
new CarItem { OfficeId = 1, ItemId = 1, Brand = "Audi", Model = "A228", Price = 4, StockBalance = 14 },
new CarItem { OfficeId = 1, ItemId = 2, Brand = "Audi", Model = "Super", Price = 44, StockBalance = 5 },
new CarItem { OfficeId = 2, ItemId = 3, Brand = "Scoda", Model = "Logan", Price = 47, StockBalance = 9 },
new CarItem { OfficeId = 2, ItemId = 4, Brand = "Scoda", Model = "Spider", Price = 78, StockBalance = 3 }
);
}
Manually I added an office called BSU.
And in main function I write this:
using (EFDataBaseContext db = new EFDataBaseContext())
{
Office office = mainOffice.Dealerships.FirstOrDefault(of => of.Brand == "BSU");
CarItem carItem = new CarItem(office.Brand, "BSss", 2222, 4);
office.CarsDataBase ??= new EFDataBase(office);
office.CarsDataBase.Create(carItem);
}
Adding a new CarItem to the BSU somehow magically creates a new office named BSU in my database every time a new CarItem is added to the BSU.
using (EFDataBaseContext db = new EFDataBaseContext())
{
Office office = mainOffice.Dealerships.FirstOrDefault(of => of.Brand == "Audi");
CarItem carItem = new CarItem(office.Brand, "AuuuU", 2222, 4);
office.CarsDataBase ??= new EFDataBase(office);
office.CarsDataBase.Create(carItem);
}
Adding a new CarItem to an Audi, on the other hand, does absolutely nothing. No new cars with the Audi brand appear in the database, and nothing at all.
Seems like you're over complicating things
Adding a new Car to an existing Office should perhaps looks like:
var ctx = new EFDatabaseContext();
var off = ctx.Offices.FirstOrDefault(o => o.Type == "Main" and o.Brand == "Audi");
off.Cars.Add(new CarItem(off.Brand, "AuuuU", 2222, 4));
ctx.SaveChanges();
Find the office, add a car, save the changes
This model I would like flat into a view model but the Current Output is not correct it is setting all the ChildProductId to the last value. I am creating one List<SubscriptionViewModel> and then creating multiple SubscriptionViewModel and adding to the collection.
List<Subscription> ListOfSubscriptions = new List<Subscription>();
List<SubscriptionChild> SubscriptionChild = new List<SubscriptionChild>();
SubscriptionChild.Add(new SubscriptionChild() { ChildProductId = 1, ChildProductName = "Child 1" });
SubscriptionChild.Add(new SubscriptionChild() { ChildProductId = 2, ChildProductName = "Child 2" });
ListOfSubscriptions.Add(new Subscription() { SubscriptionId = 1, ParentProductId=1, ParentProductName = "Product 1",ListOfSubscriptionChild= SubscriptionChild });
SubscriptionChild.Clear();
ListOfSubscriptions.Add(new Subscription() { SubscriptionId = 2, ParentProductId = 2, ParentProductName = "Product 2"});
SubscriptionChild.Clear();
SubscriptionChild.Add(new SubscriptionChild() { ChildProductId = 3, ChildProductName = "Child 3" });
SubscriptionChild.Add(new SubscriptionChild() { ChildProductId = 4, ChildProductName = "Child 4" });
ListOfSubscriptions.Add(new Subscription() { SubscriptionId = 3, ParentProductId = 3, ParentProductName = "Product 3", ListOfSubscriptionChild = SubscriptionChild });
List<SubscriptionViewModel> SubscriptionViewModel = new List<SubscriptionViewModel>();
foreach (var Subscription in ListOfSubscriptions)
{
SubscriptionViewModel vm = new SubscriptionViewModel();
vm.SubscriptionId = Subscription.SubscriptionId;
vm.ParentProductId = Subscription.ParentProductId;
vm.ParentProductName = Subscription.ParentProductName;
int count = Subscription.ListOfSubscriptionChild == null ? 0 : Subscription.ListOfSubscriptionChild.Count;
if (count == 0) {
SubscriptionViewModel.Add(vm);
}
else
{
var listOfChild = Subscription.ListOfSubscriptionChild.ToList();
foreach (var item in listOfChild)
{
vm.ChildProductId = item.ChildProductId;
vm.ChildProductName = item.ChildProductName;
SubscriptionViewModel.Add(vm);
}
}
}
foreach (var item in SubscriptionViewModel)
{
Console.WriteLine(string.Format("SubscriptionId{0} ParentProductId-{1} ChildProductId-{2}", item.SubscriptionId, item.ParentProductId, item.ChildProductId));
}
class Subscription
{
public int SubscriptionId { get; set; }
public int ParentProductId { get; set; }
public string ParentProductName { get; set; }
public List<SubscriptionChild> ListOfSubscriptionChild { get; set; }
}
class SubscriptionChild
{
public string ChildProductName { get; set; }
public int ChildProductId { get; set; }
}
class SubscriptionViewModel
{
public int SubscriptionId { get; set; }
public int ParentProductId { get; set; }
public string ParentProductName { get; set; }
public string ChildProductName { get; set; }
public int ChildProductId { get; set; }
}
Current Output
SubscriptionId1 ParentProductId-1 ChildProductId-4
SubscriptionId1 ParentProductId-1 ChildProductId-4
SubscriptionId2 ParentProductId-2 ChildProductId-0
SubscriptionId3 ParentProductId-3 ChildProductId-4
SubscriptionId3 ParentProductId-3 ChildProductId-4
expected outcome
SubscriptionId1 ParentProductId-1 ChildProductId-1
SubscriptionId1 ParentProductId-1 ChildProductId-2
SubscriptionId2 ParentProductId-2 ChildProductId-0
SubscriptionId3 ParentProductId-3 ChildProductId-3
SubscriptionId3 ParentProductId-3 ChildProductId-4
You're overwriting your SubscriptionViewModel for all of your children. You need to create a new one for each child:
foreach (var Subscription in ListOfSubscriptions)
{
int count = Subscription.ListOfSubscriptionChild == null ? 0 : Subscription.ListOfSubscriptionChild.Count;
if (count == 0)
{
SubscriptionViewModel vm = new SubscriptionViewModel();
vm.SubscriptionId = Subscription.SubscriptionId;
vm.ParentProductId = Subscription.ParentProductId;
vm.ParentProductName = Subscription.ParentProductName;
SubscriptionViewModel.Add(vm);
}
else
{
var listOfChild = Subscription.ListOfSubscriptionChild.ToList();
foreach (var item in listOfChild)
{
// Instantiate a new model for each child
SubscriptionViewModel vm = new SubscriptionViewModel();
vm.SubscriptionId = Subscription.SubscriptionId;
vm.ParentProductId = Subscription.ParentProductId;
vm.ParentProductName = Subscription.ParentProductName;
vm.ChildProductId = item.ChildProductId;
vm.ChildProductName = item.ChildProductName;
SubscriptionViewModel.Add(vm);
}
}
}
Good day
I'm new to MVC and database relationships.
So i am creating a system of services (product ordering) I understand that there must be a 1: N (One to Many) relationship since a customer can order many products.
I have 2 tables, the first table stores the data of the person requesting the service and the ID generated in this case the name of the variable is REQ_NO, and the second table stores the products requested by the customer.
My problem is the following, How can I assign the ID of the customer that is generated in the database to the products that it asks for, for example: If the customer is generated, ID 304 asks for 2 products, those products are assigned ID 304
NOTE:
TB_CS_TEST2 Is for customer data and req_no
TB_CS_TEST Is for products with req_no assigned form TB_CS_TEST2
Here is my code
Class
public partial class TB_CS_TEST2
{
public decimal REQ_NO { get; set; }
public string REQUESTOR_EMPNO { get; set; }
public string DEPT_CD { get; set; }
public string ORG_NAME { get; set; }
public string EMAIL_ID { get; set; }
public string APPROVER1 { get; set; }
public string APPROVER2 { get; set; }
public Nullable<decimal> TOTAL_AMOUNT { get; set; }
public Nullable<System.DateTime> REQUEST_DATE { get; set; }
public Nullable<System.DateTime> APPROVAL_DATE { get; set; }
public Nullable<System.DateTime> EVENT_DATE { get; set; }
public string EVENT_PLACE { get; set; }
public string PURPOSE { get; set; }
public string REMARKS { get; set; }
public string STATUS { get; set; }
public Nullable<System.DateTime> CRT_DATE { get; set; }
public string EXT { get; set; }
public virtual TB_CS_TEST TB_CS_TEST { get; set; }
}
public partial class TB_CS_TEST
{
public decimal REQ_NO { get; set; }
public Nullable<decimal> SEQ_NO { get; set; }
public Nullable<decimal> ITEM_ID { get; set; }
public Nullable<decimal> QUANTITY { get; set; }
public string UOM { get; set; }
public Nullable<decimal> UNIT_PRICE { get; set; }
public Nullable<decimal> EXTENDED_AMT { get; set; }
public Nullable<System.DateTime> CRT_DATE { get; set; }
public virtual TB_CS_TEST2 TB_CS_TEST2 { get; set; }
}
Controllers
public class DataHeaderController : Controller
{
//
// GET: /DataHeader/
public ActionResult DataHeader()
{
List<MvcApplication31.TB_CS_TEST2> hdr = new List<MvcApplication31.TB_CS_TEST2> { new TB_CS_TEST2 { REQ_NO = 0, REQUESTOR_EMPNO = "", DEPT_CD = "", ORG_NAME = "", EMAIL_ID = "", APPROVER1 = "", APPROVER2 = "", TOTAL_AMOUNT = 0, REQUEST_DATE = DateTime.Now, APPROVAL_DATE = DateTime.Now, EVENT_DATE = DateTime.Now, EVENT_PLACE = "", PURPOSE = "", REMARKS = "", STATUS = "", EXT = "" } };
Entities db = new Entities();
IEnumerable<SelectListItem> listplace = db.TB_RST_SVC_PLACE.Select(c => new SelectListItem
{
Value = c.NAMEPLACE,
Text = c.NAMEPLACE
}
);
// ViewData["NAMEPLACE"] = new SelectList(db.TB_RST_SVC_PLACE, "NAMEPLACE", "NAMEPLACE");
ViewData["NAMEPLACE"] = listplace;
IEnumerable<SelectListItem> listapp = db.TB_RST_SVC_APPROVERS.Select(c => new SelectListItem
{
Value = c.EMAIL_APP,
Text = c.NAME_APP
}
);
ViewData["APPROVER2"] = listapp;
return View(hdr);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult DataHeader(List<MvcApplication31.TB_CS_TEST2> hdr)
{
Entities db = new Entities();
IEnumerable<SelectListItem> listplace = db.TB_RST_SVC_PLACE.Select(c => new SelectListItem
{
Value = c.NAMEPLACE,
Text = c.NAMEPLACE
}
);
// ViewData["NAMEPLACE"] = new SelectList(db.TB_RST_SVC_PLACE, "NAMEPLACE", "NAMEPLACE");
ViewData["NAMEPLACE"] = listplace;
IEnumerable<SelectListItem> listapp = db.TB_RST_SVC_APPROVERS.Select(c => new SelectListItem
{
Value = c.EMAIL_APP,
Text = c.NAME_APP
}
);
ViewData["APPROVER2"] = listapp;
if (ModelState.IsValid)
{
using (Entities cd = new Entities())
{
foreach (var p in hdr)
{
p.CRT_DATE = DateTime.Now;
cd.TB_CS_TEST2.Add(p);
}
cd.SaveChanges();
ModelState.Clear();
hdr = new List<MvcApplication31.TB_CS_TEST2> { new TB_CS_TEST2 { REQ_NO = 0, REQUESTOR_EMPNO = "", DEPT_CD = "", ORG_NAME = "", EMAIL_ID = "", APPROVER1 = "", APPROVER2 = "", TOTAL_AMOUNT = 0, REQUEST_DATE = DateTime.Now, APPROVAL_DATE = DateTime.Now, EVENT_DATE = DateTime.Now, EVENT_PLACE = "", PURPOSE = "", REMARKS = "", STATUS = "", EXT = "" } };
}
}
return View(hdr);
}
}
public class BulkController : Controller
{
//
// GET: /Bulk/
public ActionResult Bulk()
{
//List<MvcApplication31.TB_CS_TEST> ci = new List<MvcApplication31.TB_CS_TEST> { new TB_CS_TEST { REQ = 0, CONTACTNO = "", CONTACTPERSON = "" } };
List<MvcApplication31.TB_CS_TEST> ci = new List<MvcApplication31.TB_CS_TEST> { new TB_CS_TEST { REQ_NO = 0, SEQ_NO = 0, ITEM_ID = 0, QUANTITY = 0, UOM = "", UNIT_PRICE = 0, EXTENDED_AMT = 0 } };
Entities db = new Entities();
IEnumerable<SelectListItem> listplace = db.TB_RST_SVC_PLACE.Select(c => new SelectListItem
{
Value = c.NAMEPLACE,
Text = c.NAMEPLACE
}
);
// ViewData["NAMEPLACE"] = new SelectList(db.TB_RST_SVC_PLACE, "NAMEPLACE", "NAMEPLACE");
ViewData["NAMEPLACE"] = listplace;
IEnumerable<SelectListItem> listapp = db.TB_RST_SVC_APPROVERS.Select(c => new SelectListItem
{
Value = c.EMAIL_APP,
Text = c.NAME_APP
}
);
ViewData["APPROVER2"] = listapp;
IEnumerable<SelectListItem> listproduct = db.TB_POS_PRODUCTS.Select(c => new SelectListItem
{
Value = c.ID.ToString(),
Text = c.DESCRIPTION
}
);
ViewData["PRODUCTS"] = new SelectList(db.TB_POS_PRODUCTS, "ID", "DESCRIPTION");
//ViewData["DESCRIPTION"] = listproduct;
return View(ci);
}
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Bulk(List<MvcApplication31.TB_CS_TEST> ci)
{
Entities db = new Entities();
IEnumerable<SelectListItem> listplace = db.TB_RST_SVC_PLACE.Select(c => new SelectListItem
{
Value = c.NAMEPLACE,
Text = c.NAMEPLACE
}
);
// ViewData["NAMEPLACE"] = new SelectList(db.TB_RST_SVC_PLACE, "NAMEPLACE", "NAMEPLACE");
ViewData["NAMEPLACE"] = listplace;
IEnumerable<SelectListItem> listapp = db.TB_RST_SVC_APPROVERS.Select(c => new SelectListItem
{
Value = c.EMAIL_APP,
Text = c.NAME_APP
}
);
ViewData["APPROVER2"] = listapp;
IEnumerable<SelectListItem> listproduct = db.TB_POS_PRODUCTS.Select(c => new SelectListItem
{
Value = c.ID.ToString(),
Text = c.DESCRIPTION
}
);
ViewData["PRODUCTS"] = new SelectList(db.TB_POS_PRODUCTS, "ID", "DESCRIPTION");
//ViewData["DESCRIPTION"] = listproduct;
if (ModelState.IsValid)
{
using (Entities dc = new Entities())
{
foreach (var i in ci)
{
i.CRT_DATE = DateTime.Now;
dc.TB_CS_TEST.Add(i);
}
dc.SaveChanges();
ViewBag.Message = "Data Successfully saved!";
ModelState.Clear();
//ci = new List<MvcApplication31.TB_CS_TEST> { new MvcApplication31.TB_CS_TEST { CONTACTID = 0, CONTACTNO = "", CONTACTPERSON = "" } };
ci = new List<MvcApplication31.TB_CS_TEST> { new MvcApplication31.TB_CS_TEST { REQ_NO = 0, SEQ_NO = 0, ITEM_ID = 0, QUANTITY = 0, UOM = "", UNIT_PRICE = 0, EXTENDED_AMT = 0 } };
}
}
return View(ci);
}
}
Thanks for your help!
For experience i do the next steps.
if (ModelState.IsValid)
{
using (Entities dc = new Entities())
{
//decimal dcr = dc.TB_CS_TEST2.DefaultIfEmpty().Max(u => u.REQ_NO); THIS CODE PASS DE ID FROM THE OTHER TABLE AND PUT IN A VARIABLE AND USE IN SAVECHANGES
foreach (var i in ci)
{
decimal dcr = dc.TB_CS_TEST2.DefaultIfEmpty().Max(u => u.REQ_NO);
i.REQ_NO = dcr;
i.CRT_DATE = DateTime.Now;
dc.TB_CS_TEST.Add(i);
}
//var cust = new TB_CS_TEST2();
//var pedido = new TB_CS_TEST { TB_CS_TEST2 = cust };
dc.SaveChanges();
SendEmail();
if (dc.SaveChanges() > 0)
{
ViewBag.Message = "Data Successfully saved!";
}
else
{
ViewBag.Message = "Error";
}
ModelState.Clear();
//ci = new List<MvcApplication31.TB_CS_TEST> { new MvcApplication31.TB_CS_TEST { CONTACTID = 0, CONTACTNO = "", CONTACTPERSON = "" } };
ci = new List<MvcApplication31.TB_CS_TEST> { new MvcApplication31.TB_CS_TEST { REQ_NO = 0, SEQ_NO = 0, ITEM_ID = 0, QUANTITY = 0, UOM = "", UNIT_PRICE = 0, EXTENDED_AMT = 0 } };
}
}
return View(ci);
I have the next mongo document structure :
_id
-countryCode
-keywordID
-name
-displayName
-categories:[Array]
-_id
-name
-position
-canonical
I would like to get all the keywords that are in a specific category only knowing the category's ID. I am using the mongo C# driver but don't know how could I check what's inside that array.
I would like to send a list with the category ID's and get back all the keywords that have a category from that list.
public async Task<List<Keyword>> GetKeywords(List<long> keywordCatIds, string countryCode)
{
var mongoCollection = MongoDatabase.GetCollection<Keyword>("Keywords");
try
{
FilterDefinition<Keyword> mongoFilter = Builders<Keyword>.Filter.In(c=>c.Categories, keywordCatIds);
return await mongoCollection.Find(mongoFilter,null).ToListAsync<Keyword>();
}
catch (Exception ex)
{
Logger.Error(ex, "Multiple ids for Country Code: {0}, ids: {1}", countryCode, string.Join(',', keywordCatIds.Select(s => s)));
return null;
}
}
Your In function looks like a "categories._id" filter in normal mongoDB. Which transitions into an ElemMatch. I created a project which fills the db, than selects
all the keywords that are in a specific category only knowing the category's ID
public class CustomID
{
public string CountryCode { get; set; }
public long KeywordId { get; set; }
public string Name { get; set; }
}
public class Keyword
{
[BsonId]
public CustomID Id { get; set; }
public List<Category> Categories { get; set; }
}
public class Category
{
[BsonId]
public long Id { get; set; }
public string Name { get; set; }
public int Position { get; set; }
}
internal class Program
{
public static IMongoDatabase MongoDatabase { get; private set; }
public static async Task Main()
{
var conventionPack = new ConventionPack
{
new CamelCaseElementNameConvention()
};
ConventionRegistry.Register(
"CustomConventionPack",
conventionPack,
t => true);
var client = new MongoClient();
MongoDatabase = client.GetDatabase("SO");
var ret = await GetKeywords(new List<long> {1L, 2L}, "HU-hu");
// ret is A and B. C is filtered out because no category id of 1L or 2L, D is not HU-hu
}
public static async Task<List<Keyword>> GetKeywords(List<long> keywordCatIds, string countryCode)
{
var mongoCollection = MongoDatabase.GetCollection<Keyword>("keywords");
// be ware! removes all elements. For debug purposes uncomment>
//await mongoCollection.DeleteManyAsync(FilterDefinition<Keyword>.Empty);
await mongoCollection.InsertManyAsync(new[]
{
new Keyword
{
Categories = new List<Category>
{
new Category {Id = 1L, Name = "CatA", Position = 1},
new Category {Id = 3L, Name = "CatC", Position = 3}
},
Id = new CustomID
{
CountryCode = "HU-hu",
KeywordId = 1,
Name = "A"
}
},
new Keyword
{
Categories = new List<Category>
{
new Category {Id = 2L, Name = "CatB", Position = 2}
},
Id = new CustomID
{
CountryCode = "HU-hu",
KeywordId = 2,
Name = "B"
}
},
new Keyword
{
Categories = new List<Category>
{
new Category {Id = 3L, Name = "CatB", Position = 2}
},
Id = new CustomID
{
CountryCode = "HU-hu",
KeywordId = 3,
Name = "C"
}
},
new Keyword
{
Categories = new List<Category>
{
new Category {Id = 1L, Name = "CatA", Position = 1}
},
Id = new CustomID
{
CountryCode = "EN-en",
KeywordId = 1,
Name = "EN-A"
}
}
});
var keywordFilter = Builders<Keyword>.Filter;
var categoryFilter = Builders<Category>.Filter;
var mongoFilter =
keywordFilter.ElemMatch(k => k.Categories, categoryFilter.In(c => c.Id, keywordCatIds)) &
keywordFilter.Eq(k => k.Id.CountryCode, countryCode);
return await mongoCollection.Find(mongoFilter).ToListAsync();
}
}
I have a Linq question: (DotNet Framework 4.0)
I have the following classes:
public class Employee
{
public Guid? EmployeeUUID { get; set; }
public string SSN { get; set; }
}
public class JobTitle
{
public Guid? JobTitleSurrogateKey { get; set; }
public string JobTitleName { get; set; }
}
public class EmployeeToJobTitleMatchLink
{
public EmployeeToJobTitleMatchLink()
{
this.TheJobTitle = new JobTitle() { JobTitleSurrogateKey = Guid.NewGuid(), JobTitleName = "SomeJobTitle:" + Guid.NewGuid().ToString("N") };
}
public Guid LinkSurrogateKey { get; set; }
/* Related Objects */
public Employee TheEmployee { get; set; }
public JobTitle TheJobTitle { get; set; }
}
public class Organization
{
public Organization()
{
this.Links = new List<EmployeeToJobTitleMatchLink>();
}
public int OrganizationSurrogateKey { get; set; }
public ICollection<EmployeeToJobTitleMatchLink> Links { get; set; }
}
In my code below, I can compare 2 child-collections and get the results I need (in "matches1".
Here I am using the "SSN" string property to compare and find the overlaps. And the Console.Write for matches1 works as I expect.
What I don't know how to do is compare the first child collection (org10) to all the children in (allOtherOrgsExceptOrg10 (all the Organizations and all the Links of these Organizations )
The commented out code shows kinda what I'm trying to do, one of my many feeble attempts today.
But basically, match2 would be populated with all the SSN overlaps...but comparing org10 with allOtherOrgsExceptOrg10, all their "Links", and their Employee.SSN's.
org10 overlaps with org20 with "AAA", so match2 would contain "AAA". and org10 overlaps with org30 with "BBB" so match2 would contain "BBB".
Organization org10 = new Organization();
org10.OrganizationSurrogateKey = 10;
Employee e11 = new Employee() { SSN = "AAA", EmployeeUUID = new Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA") };
EmployeeToJobTitleMatchLink link11 = new EmployeeToJobTitleMatchLink();
link11.TheEmployee = e11;
org10.Links.Add(link11);
Employee e12 = new Employee() { SSN = "BBB", EmployeeUUID = new Guid("BBBBBBBB-BBBB-BBBB-BBBB-BBBBBBBBBBBB") };
EmployeeToJobTitleMatchLink link12 = new EmployeeToJobTitleMatchLink();
link12.TheEmployee = e12;
org10.Links.Add(link12);
Organization org20 = new Organization();
org20.OrganizationSurrogateKey = 20;
Employee e21 = new Employee() { SSN = "AAA", EmployeeUUID = new Guid("AAAAAAAA-AAAA-AAAA-AAAA-AAAAAAAAAAAA") };
EmployeeToJobTitleMatchLink link21 = new EmployeeToJobTitleMatchLink();
link21.TheEmployee = e21;
org20.Links.Add(link21);
Employee e22 = new Employee() { SSN = "CCC", EmployeeUUID = new Guid("CCCCCCCC-CCCC-CCCC-CCCC-CCCCCCCCCCCC") };
EmployeeToJobTitleMatchLink link22 = new EmployeeToJobTitleMatchLink();
link22.TheEmployee = e22;
org20.Links.Add(link22);
Organization org30 = new Organization();
org30.OrganizationSurrogateKey = 30;
Employee e31 = new Employee() { SSN = "BBB", EmployeeUUID = new Guid("BBBBBBBB-BBBB-BBBB-BBBB-BBBBBBBBBBBB") };
EmployeeToJobTitleMatchLink link31 = new EmployeeToJobTitleMatchLink();
link31.TheEmployee = e31;
org30.Links.Add(link31);
Employee e32 = new Employee();
e32.SSN = "ZZZ";
EmployeeToJobTitleMatchLink link32 = new EmployeeToJobTitleMatchLink();
link32.TheEmployee = e32;
org30.Links.Add(link32);
IList<Organization> allOtherOrgsExceptOrg10 = new List<Organization>();
/* Note, I did not add org10 here */
allOtherOrgsExceptOrg10.Add(org20);
allOtherOrgsExceptOrg10.Add(org30);
IEnumerable<EmployeeToJobTitleMatchLink> matches1 =
org10.Links.Where(org10Link => org20.Links.Any(org20Link => org20Link.TheEmployee.SSN.Equals(org10Link.TheEmployee.SSN, StringComparison.OrdinalIgnoreCase)));
IEnumerable<EmployeeToJobTitleMatchLink> matches2 = null;
//org10.Links.Where(org10Link => ( allOtherOrgs.Where ( anyOtherOrg => anyOtherOrg.Links.Any(dbSideChild => dbSideChild.TheEmployee.SSN == org10Link.TheEmployee.SSN)) );
if (null != matches1)
{
foreach (EmployeeToJobTitleMatchLink link in matches1)
{
Console.WriteLine(string.Format("matches1, SSN = {0}", link.TheEmployee.SSN));
}
}
if (null != matches2)
{
foreach (EmployeeToJobTitleMatchLink link in matches2)
{
Console.WriteLine(string.Format("matches2, SSN = {0}", link.TheEmployee.SSN));
}
}
matches2 =
allOtherOrgsExceptOrg10.SelectMany(x => x.Links)
.Where(x => org10.Links.Select(o => o.TheEmployee.SSN).Contains(x.TheEmployee.SSN));
You can use the SelectMany on the allOther collection to select all Links over all org's. Then check if any SSN is inside the org10 List.
See: http://msdn.microsoft.com/en-us/library/system.linq.enumerable.selectmany(v=vs.100).aspx
You can use SelectMany to flatten out the collection and then use it just like you have for matches1
IEnumerable<EmployeeToJobTitleMatchLink> matches2 =
org10.Links.Where(
org10Link =>
allOtherOrgsExceptOrg10.SelectMany(allOtherOrgs => allOtherOrgs.Links).Any(
anyOtherLink =>
anyOtherLink.TheEmployee.SSN.Equals(org10Link.TheEmployee.SSN, StringComparison.OrdinalIgnoreCase)));
The SelectMany will make it seem like one IEnumerable instead of and IEnumerable of an IEnumerable.