Accessing properties from multiple classes - c#

I am creating a web application and I have two classes:
public class MOrderMain
{
public int ID { get; set; }
public int CompanyID { get; set; }
public string CompanyName { get; set; }
public DateTime OrderDate { get; set; }
public string BillingName { get; set; }
public string BillingAddress { get; set; }
public string DeliveryName { get; set; }
public string DeliveryAddress { get; set; }
}
public class MOrder
{
public int ID { get; set; }
public int OrhID { get; set; }
public int ProID { get; set; }
public string Name { get; set; }
public int Quantity { get; set; }
public double Rate { get; set; }
public double Amount { get; set; }
public int DeliveredQty { get; set; }
}
I would like to retrieve details from both classes. For example, I want to get
ID and Billing Name from class MorderMain and all the properties from class MOrder. How can I do this?
I am getting the values by database. I have the query but how will I assign the data and how will I retrieve from both?
var mylist = new List<MOrder>();
_con = _db.GetConnection();
if (_con.State.Equals(ConnectionState.Closed))
{
_con.Open();
}
_cmd = new SqlCommand("Get_All_Order_Details", _con)
{ CommandType = CommandType.StoredProcedure };
_dr = _cmd.ExecuteReader();
while (_dr.Read())
{
mylist.Add(new MOrder
{
ID = Convert.ToInt32(_dr["ordID"]),
OrhID = Convert.ToInt32(_dr["orhID"]),
ProID = Convert.ToInt32(_dr["proID"]),
Name = _dr["pName"].ToString(),
Quantity = Convert.ToInt32(_dr["ordQty"]),
Rate = Convert.ToDouble(_dr["ordRate"]),
Amount = Convert.ToDouble(_dr["ordAmount"]),
DeliveredQty = Convert.ToInt32(_dr["ordQtyDelivered"])
});
}
return mylist;

Since you are retrieving data from both tables in your database but want to combine them in your application, the solution would be to create a single class that contains the data you return from your stored procedure:
public class MAllOrderDetails
{
public int ID { get; set; }
public string BillingName { get; set; }
// include the other billing details you want here
public int OrhID { get; set; }
public int ProID { get; set; }
public string Name { get; set; }
public int Quantity { get; set; }
public double Rate { get; set; }
public double Amount { get; set; }
public int DeliveredQty { get; set; }
}
Then, your query changes to filling in a List<MAllOrderDetails>.
This leaves your application with only dealing with a collection of a single class with all the data nicely contained in single objects.
var mylist = new List<MAllOrderDetails>();
//...
while (_dr.Read())
{
mylist.Add(new MAllOrderDetails
{
ID = Convert.ToInt32(_dr["ordID"]),
BillingName = _dr["BillingName"].ToString(),
// etc.
OrhID = Convert.ToInt32(_dr["orhID"]),
ProID = Convert.ToInt32(_dr["proID"]),
Name = _dr["pName"].ToString(),
Quantity = Convert.ToInt32(_dr["ordQty"]),
Rate = Convert.ToDouble(_dr["ordRate"]),
Amount = Convert.ToDouble(_dr["ordAmount"]),
DeliveredQty = Convert.ToInt32(_dr["ordQtyDelivered"])
});
}
Update
You could probably get away with this as the closest solution to not creating an additional classes:
class MAllOrderDetails
{
public MOrder Order { get; set; }
public MOrderMain OrderMain { get; set; }
}
I feel, though, that from a maintainability standpoint, this will cause you more headaches than just creating additional classes.

Related

Asp.net core mvc ViewModel with 2 Models

I'm building a feature with a jquery datatable, the idea is to have a list of stores in the parent row, and then when expanding the parent to list all the licensed terminals in child rows that are linked to the store parent row by a StoreLicenseId column. The issue I am having is that I have a ViewModel with two models, one for the list of stores and one for the licensed terminals. I'm busy building the method into my controller, my problem is in the second part of the method where I new up "StoreLicenseDetails = sl.Select(tl => new TerminalListViewModel()", all the references to tl.terminalId and tl.Terminalname. I get this error "StoreListViewModel does not contain a definition for TerminalID and no accessible extension method". I can see why this is happening, so my question really is, how do I include this "second" TerminalListViewModel into my method to form part of the query ?
ViewModel
public partial class StoreListViewModel
{
public List<TerminalListViewModel> StoreLicenseDetails { get; set; } = null!;
public int Id { get; set; }
public Guid StoreLicenseId { get; set; }
[DisplayName("Store Name")]
public string StoreName { get; set; } = null!;
[DisplayName("App One Licenses")]
public int QtyAppOneLicenses { get; set; }
[DisplayName("App Two Licenses")]
public int QtyAppTwoLicenses { get; set; }
[DisplayName("Date Licensed")]
public DateTime DateLicensed { get; set; }
[DisplayName("Licensed Days")]
public int LicenseDays { get; set; }
[DisplayName("Is License Active")]
public bool LicenseIsActive { get; set; }
}
public partial class TerminalListViewModel
{
public int Id { get; set; }
public Guid StoreLicenseId { get; set; }
public Guid TerminalId { get; set; }
public string TerminalName { get; set; } = null!;
public string LicenseType { get; set; } = null!;
public int TerminalLicenseDays { get; set; }
public DateTime DateLicensed { get; set; }
public bool LicenseIsActive { get; set; }
public bool IsDecommissioned { get; set; }
public DateTime LastLicenseCheck { get; set; }
}
Controller Method
//sl = StoreList
//tl = TerminalList
public IEnumerable<StoreListViewModel> GetStoreList()
{
return GetStoreList().GroupBy(sl => new { sl.StoreLicenseId, sl.StoreName, sl.QtyAppOneLicenses,
sl.QtyAppTwoLicenses, sl.DateLicensed, sl.LicenseDays,
sl.LicenseIsActive })
.Select(sl => new StoreListViewModel()
{
StoreName = sl.Key.StoreName,
QtyAppOneLicenses = sl.Key.QtyAppOneLicenses,
QtyAppTwoLicenses = sl.Key.QtyAppTwoLicenses,
DateLicensed = sl.Key.DateLicensed,
LicenseDays = sl.Key.LicenseDays,
LicenseIsActive = sl.Key.LicenseIsActive,
StoreLicenseId = sl.FirstOrDefault().StoreLicenseId,
StoreLicenseDetails = sl.Select(tl => new TerminalListViewModel()
{
StoreLicenseId = tl.StoreLicenseId,
TerminalId = tl.TerminalId,
TerminalName = tl.TerminalName,
}).ToList()
}).ToList();
}
Based on the error,I suppose your GetStoreList() method returns List<OrderListViewModel> ,but your OrderListViewModel doesn't contains properties of TerminalListViewModel,So you got the error
GetStoreList() method should return List<SourceModel>( Source is the model which contains all the properties of StoreListViewModel and TerminalListViewModel)
For example,the link your provided:Multiple child rows in datatable, data from sql server in asp.net core
public class OrderList
{
//source of properties of OrderListViewModel(parent rows)
public int OrderId { get; set; }
public string Customer { get; set; }
public string OrderDate { get; set; }
//source of properties of OrderListDetailViewModel(child rows)
public int KimlikId { get; set; }
public string Product { get; set; }
public string Color { get; set; }
public int Qntty { get; set; }
}
public class OrderListViewModel
{
public int OrderId { get; set; }
public string Customer { get; set; }
public string OrderDate { get; set; }
public List<OrderListDetailViewModel> OrderListDetails { get; set; }
}
public class OrderListDetailViewModel
{
public int KimlikId { get; set; }
public string Product { get; set; }
public string Color { get; set; }
public int Qntty { get; set; }
}
Orderlist contains all columns OrderListViewModel and OrderListDetailViewModel needs.
When it comes to your case,you should
create 3 models (source,parentrow,childrows)
model for parentrows contains the properties
StoreLicenseId,StoreName, QtyAppOneLicenses,QtyAppTwoLicenses, DateLicensed, LicenseDays,LicenseIsActive
and model for childrows contains the other properties of source model
If you still have questions,please show the data you pulled form db,and I'll write a demo for you

C# Deep Clone of a List Data

I have properties as below;
public class Employer
{
public int IDNumber { get; set; }
public DateTime RegDate { get; set; }
public List<BioData> BioInfo { get; set; }
}
BioData.cs
public class BioData
{
public int IndexID { get; set; }
public string Description { get; set; }
public int Age { get; set; }
public double Salary { get; set; }
}
I want to Deep Clone Employer List including all the fields and properties to the same Employer list.
One approach is to provide a copy-constructor for BioData. You should also seal the class, so you don't need to worry about handling copying derived class data:
public sealed class BioData
{
public BioData()
{
// Initialise members or not, as you like.
}
public BioData(BioData other)
{
IndexID = other.IndexID;
Description = other.Description;
Age = other.Age;
Salary = other.Salary;
}
public int IndexID { get; set; }
public string Description { get; set; }
public int Age { get; set; }
public double Salary { get; set; }
}
Then you can clone the list like so:
var clone = BioInfo.Select(item => new BioData(item)).ToList();
You can also use a method or the IClonable Interface to clone your data.
I prefere my own method with a clear name (shallow or deep clone):
public sealed class Employer
{
public int IDNumber { get; set; }
public DateTime RegDate { get; set; }
public List<BioData> BioInfo { get; set; }
public Employer DeepClone()
{
Employer loClone = new Employer()
{
IDNumber = this.IDNumber,
RegDate = this.RegDate
};
if (this.BioInfo != null)
loClone.BioInfo = this.BioInfo.Select(item => item.DeepClone()).ToList();
return loClone;
}
}
public sealed class BioData
{
public int IndexID { get; set; }
public string Description { get; set; }
public int Age { get; set; }
public double Salary { get; set; }
public BioData DeepClone()
{
//Can also use here
//return this.MemberwiseClone() as BioData;
return new BioData()
{
IndexID = this.IndexID,
Description = String.Copy(this.Description),
Age = this.Age,
Salary = this.Salary
};
}
}
UPDATE
To copy the entries from an existing list in the same list, you can use LINQ.
(ToList is necessary):
List<Employer> loList = new List<Employer>();
loList.ToList().ForEach(item => loList.Add(item.DeepClone()));

Way to create composite objects from a single (flat) database query

I am getting product data from our ERP through SQL queries whereby the returned data is very flat- at the Size level. A product has 3 levels:
Style
Colours
Sizes
A style has many colours and a colour has many sizes.
I have created the following models:
public class Ap21Style
{
public int StyleIdx;
public string StyleCode;
public IList<Ap21Clr> Clrs { get; set; } = new List<Ap21Clr>();
}
public class Ap21Clr
{
public int ClrIdx { get; set; }
public string ColourCode { get; set; }
public string ColourName { get; set; }
public string ColourTypeCode { get; set; }
public string ColourTypeName { get; set; }
public IList<Ap21Sku> Skus { get; set; } = new List<Ap21Sku>();
}
public class Ap21Sku
{
public int SkuIdx { get; set; }
public string SizeCode { get; set; }
public int SizeSequence { get; set; }
public string Barcode { get; set; }
}
My ProductResult looks like this:
public int StyleIdx { get; set; }
public int ClrIdx { get; set; }
public int SkuIdx { get; set; }
public string StyleCode { get; set; }
public string ColourCode { get; set; }
public string ColourName { get; set; }
public string SizeCode { get; set; }
public int SizeSequence { get; set; }
public string ColourTypeCode { get; set; }
public string ColourTypeName { get; set; }
public string Barcode { get; set; }
public string WebData { get; set; }
What would be an effective way to loop over the results and create the Ap21Style models whereby they are a composite object with Ap21Clr's, then at the row level, the Colours have Ap21Sku's?
Assuming something like this
List<ProductResult> products = GetPropducts();
Composing the styles would involve grouping the data by the composite keys
List<Ap21Style> results = products
.GroupBy(p => new { p.StyleIdx, p.StyleCode })
.Select(g => new Ap21Style {
StyleIdx = g.Key.StyleIdx,
StyleCode = g.Key.StyleCode,
Clrs = g.GroupBy(s => new {
s.ClrIdx,
s.ColourCode,
s.ColourName,
s.ColourTypeCode,
s.ColourTypeName
}).Select(g1 => new Ap21Clr {
ClrIdx = g1.Key.ClrIdx,
ColourCode = g1.Key.ColourCode,
ColourName = g1.Key.ColourName,
ColourTypeCode = g1.Key.ColourTypeCode,
ColourTypeName = g1.Key.ColourTypeName,
Skus = g1.Select(s => new Ap21Sku {
Barcode = s.Barcode,
SizeCode = s.SizeCode,
SizeSequence = s.SizeSequence,
SkuIdx = s.SkuIdx
}).ToList()
}).ToList()
}).ToList();

How to store specific data into list with class

i want ask about storing data into list but not all data like this,
class Category :
public class CategoryEnt
{
public int CategoryID { get; set; }
public string CategoryName { get; set; }
public int ParentID { get; set; }
public bool IsDisplayed { get; set; }
public bool IsTopCat { get; set; }
public bool IsTrending { get; set; }
public int SequenceID { get; set; }
public string Filtering { get; set; }
public string ImageURL { get; set; }
}
i just want add to list CategoryID, CategoryName, ImageUrl
while (reader.Read())
{
CategoryEnt category = new CategoryEnt();
category.CategoryID = Convert.ToInt32(reader["CategoryID"]);
category.CategoryName = reader["CategoryName"].ToString();
category.ImageURL = reader["ImageURL"].ToString();
list.Add(category);
}
the right now, rest of data include but with default/null value, i dont want rest of data include to list. how to store just specific data to list? any clue?
You cannot do that Directly, but indirectly you can achieve the same by using the following code:
List<CategoryEnt> CategoryEntList = new List<CategoryEnt>();
while (reader.Read())
{
CategoryEntList.Add(new CategoryEnt(){
CategoryID = Convert.ToInt32(reader["CategoryID"]),
CategoryName = reader["CategoryName"].ToString(),
ImageURL = reader["ImageURL"].ToString(),
});
}
var requiredValues = CategoryEntList.Select(x => new
{ CategoryID = x.CategoryID,
CategoryName = x.CategoryName,
ImageURL = x.ImageURL
}).ToList();
Now requiredValues is a List that will contains only those value that you ware specified in the Select You can proceed with that;
Try a class with just the information you require. Something like:
public class Category
{
public int CategoryID { get; set; }
public string CategoryName { get; set; }
public string ImageURL { get; set; }
}
Then you can create your original class using
public class CategoryEnt
{
public Category CategoryPrimaryDetails { get; set; }
public int ParentID { get; set; }
public bool IsDisplayed { get; set; }
public bool IsTopCat { get; set; }
public bool IsTrending { get; set; }
public int SequenceID { get; set; }
public string Filtering { get; set; }
}
And your original code becomes:
List<Category> list = new List<Category>();
while (reader.Read())
{
Category category = new Category() {
CategoryID = Convert.ToInt32(reader["CategoryID"]);
CategoryName = reader["CategoryName"].ToString();
ImageURL = reader["ImageURL"].ToString()
}
list.Add(category);
CategoryEnt detailedCategory = new CategoryEnt() {CategoryPrimaryDetails = category};
}

Class Array Defining

I cannot seem to work out how to populate a sub class...
These are the classes I have:
public class Item
{
public Meta meta { get; set; }
public Items[] objects { get; set; }
}
public class Meta
{
public int limit { get; set; }
public object next { get; set; }
public int offset { get; set; }
public object previous { get; set; }
public int total_count { get; set; }
}
public class Items
{
public Additionalprices additionalPrices { get; set; }
public string barcode { get; set; }
public Category category { get; set; }
public int categoryPosition { get; set; }
public string cdate { get; set; }
public DateTime ctime { get; set; }
public DateTime ctimeOnServer { get; set; }
public Dimensions dimensions { get; set; }
public string entityType { get; set; }
public object imageURL { get; set; }
public object[] imageURLs { get; set; }
public string longDesc { get; set; }
public string manufacturer { get; set; }
public int minQty { get; set; }
public DateTime mtime { get; set; }
public DateTime mtimeOnServer { get; set; }
public int multQty { get; set; }
public string name { get; set; }
public int objID { get; set; }
public string owner { get; set; }
public string resource_uri { get; set; }
public string sku { get; set; }
public object thumbnailURL { get; set; }
public object[] thumbnailURLs { get; set; }
public string unitPrice { get; set; }
public string uuid { get; set; }
public Variant[] variants { get; set; }
}
I want to add some dummy objects...
This is the code I have...
// Create a dummy Category
HandShake_Classes.Category categoryToUpload = new HandShake_Classes.Category();
categoryToUpload.name = "Trev Category";
// Create a dummy Item
HandShake_Classes.Item itemToUpload = new HandShake_Classes.Item();
// THIS IS WHERE MY PROBLEM IS...
itemToUpload.objects = new HandShake_Classes.Items();
// THE ERROR I AM GETTING IS Error 2 Cannot implicitly convert type 'handshake.com.HandShake_Classes.Items' to 'handshake.com.HandShake_Classes.Items[]'
// Only populate required fields at the moment
itemToUpload.objects[0].sku = "ljklj";
itemToUpload.objects[0].name = "Trevs Product";
itemToUpload.objects[0].unitPrice = "1.23";
itemToUpload.objects[0].minQty = 1;
itemToUpload.objects[0].category = categoryToUpload;
I just cannot work out how define the Items[] I think
Can anyone point me in the right direction please?
Thanks
You have to initialize the array first. Let's say you need 10 items:
itemToUpload.objects = new HandShake_Classes.Items[10];
And then you can set every array item to the new Items() instance:
itemToUpload.objects[0] = new HandShake_Classes.Items();
itemToUpload.objects[0].sku = "ljklj";
itemToUpload.objects[0].name = "Trevs Product";
itemToUpload.objects[0].unitPrice = "1.23";
itemToUpload.objects[0].minQty = 1;
itemToUpload.objects[0].category = categoryToUpload;
And just to make it clear: if you don't know how many items object property will have to handle, you should consider changing it to List<Items> instead of Items[] array:
itemToUpload.objects = new List<HandShake_Classes.Items>();
var newItem = new HandShake_Classes.Items();
newItem = new HandShake_Classes.Items();
newItem.sku = "ljklj";
newItem.name = "Trevs Product";
newItem.unitPrice = "1.23";
newItem.minQty = 1;
newItem.category = categoryToUpload;
itemToUpload.objects.Add(newItem);
Instantiate the array of type items as
itemToUpload.objects = new HandShake_Classes.Items[10];
After this instantiation, you would require to instantiate every index of the object.
For example
itemToUpload.objects[i] = new HandShake_Classes.Items();
This means you are instantiating a single object, and that object would be in array at index 'i'.
you can then set the properties of the Items in objects array by writing as
itemToUpload.objects[i].barcode
even call the functions
itemToUpload.objects[i].CalculateTax()
similarly you can use any constructors if defined.

Categories

Resources