We have Customer transactional table with multiple lookup tables with foreign keys. We want to see the 3 table joined together. Should a Repository ever join tables together, or is it only used for reading single tables?
Also if so, what does the example repository place data into? I heard it cannot know about Viewmodels etc, so what object data type would the results go into?
Repository:
void GetByCustomerTransactionId()
{
var result = from ct in CustomerTransaction
join pt in ProductType on pt.ProductTypeId equals ct.ProductTypeId
join ss in Status on s.StatusId equals ct.StatusId
select new all fields
}
Models:
public class CustomerTransaction
{
public int CustomerTransactionId{ get; set; },
public int ProductTypeId {get; set; }, //joins to ProductTypeTable
public int StatusID {get; set; }, //joins to StatusTypeTable
public string DateOfPurchase{ get; set; },
public int PurchaseAmount { get; set; },
}
public class ProductType
{
public int ProductTypeId{ get; set; }
public string ProductName { get; set; },
public string ProductDescription { get; set; },
}
public class StatusType
{
public int StatusId{ get; set; }
public string StatusName{ get; set; },
public string Description{ get; set; },
}
One of the ways to establish One-To-Many Relationships in ASP.NET Core is the Fluent API
public class CustomerTransaction
{
public int CustomerTransactionId { get; set; }
public string DateOfPurchase{ get; set; }
public int PurchaseAmount { get; set; }
// relationships
public ProductType ProductType { get; set; }
public int ProductTypeId { get; set; }
public StatusType StatusType { get; set; }
public int StatusID { get; set; }
}
public class ProductType
{
public int ProductTypeId { get; set; }
public string ProductName { get; set; }
public string ProductDescription { get; set; }
// relationships
public ICollection<CustomerTransaction> CustomerTransactions { get; set; }
}
public class StatusType
{
public int StatusId { get; set; }
public string StatusName { get; set; }
public string Description { get; set; }
// relationships
public ICollection<CustomerTransaction> CustomerTransactions { get; set; }
}
Then simply use Include to properly join them together in your result.
public void GetByCustomerTransactionId(int id)
{
var result = context.CustomerTransaction.Where(x=>x.CustomerTransactionId == id)
.Include(i=>i.ProductType)
.Include(i=>i.StatusType);
}
Considering there are foreign key constraints on the tables, you can simply do this without having to do any joins yourself
public class CustomerTransaction
{
public int CustomerTransactionId{ get; set; },
public int ProductTypeId {get; set; }, //joins to ProductTypeTable
public int StatusID {get; set; }, //joins to StatusTypeTable
public string DateOfPurchase{ get; set; },
public int PurchaseAmount { get; set; },
// Add this
public ProductType ProductType { get; set;}
public StatusType StatusType { get; set;}
}
and then on your repository simply get the CustomerTransation and it will return the joined tables too, based on their foreign key
CustomerTransaction GetByCustomerTransactionId(int id)
{
var result = ct.CustomerTransaction.Where(x => x.CustomerTransactionId == id).ToList()
return result;
}
That will give you your CustomerTransactions, their StatusType and ProductType
Related
I am trying add the cart to database but don't know how to add related Entities
My related tables are ( carts , products , productoptions , options)
How Can I add or Update those tables at the same time? And how can I set Foreign keys to related Tables
thanks...
You will create models for each of your tables (see below)
Then if you add just a child you will have to add it with the foreig nkey property populated
var test = childObj { parentPropertyId = parentPropertyIdValue}
If you add parent and child together you can just add and entity mework will take care of that. For example:
var test = new parentObj {
someProperty = someValue,
childProperty = new childObj{
//here will not have to populate the parentPropertyId
}
}
See sample models for your above tables
Use the [Key] attribute to specify your primary key
Use the [ForeignKey] attribute above your related entity property to specify which property to use as foreign key
Use an ICollection to access the children of an object
public class Carts
{
[Key]
public int Id { get; set; }
public int Userid { get; set; }
public DateTime CreatedDate { get; set; }
public ICollection<Products> Products { get; set; }
}
public class Products
{
[Key]
public int Id { get; set; }
public string SerialNumber { get; set; }
public string StockCode { get; set; }
public int CartId { get; set; }
public int Quantity { get; set; }
[ForeignKey(nameof(CartId))]
public Carts Cart { get; set; }
}
public class ProductOptions
{
[Key]
public int Id { get; set; }
public int ProductId { get; set; }
public int OptionId { get; set; }
[ForeignKey(nameof(ProductId))]
public Products Products { get; set; }
[ForeignKey(nameof(OptionId))]
public Options Options { get; set; }
}
public class Options
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public int Quantity { get; set; }
public int ParentId { get; set; }
public int GrandParentId { get; set; }
}
I have two tables from which I want to fetch the data and return it to the API for consumable purposes. There is a relationship between the two tables.
[![enter image description here][1]][1]
When I try to fetch the data, it is returning only one row which is not what I want.
How can I return all the data related to ResellerId (8435 examples)?
This is my code:
public RateSheetModel GetRateSheet(int resellerId)
{
// This only returns only one row.
// How can I get all rows for all the same Id?
var rateSheetDetails = (from r in _Context.WholesaleRateSheet
where r.ResellerId == resellerId
select r).First();
}
Models
public class WholesaleRateSheetMarkup
{
[Key]
public int RateSheetMarkupId { get; set; }
[Required]
public int ResellerId { get; set; }
[StringLength(50)]
public string RatesheetName { get; set; }
}
public class WholesaleRateSheet
{
[Key]
public int RateSheetId { get; set; }
[Required]
public int RateSheetMarkupId { get; set; }
[Required]
public int ResellerId { get; set; }
public string CountryCode { get; set; }
public string Description { get; set; }
public decimal Peak { get; set; }
public bool IsSouthAfricanRate { get; set; }
public bool IsInertnationRate { get; set; }
public bool IsSpecificRate { get; set; }
public int DestinationGroupSetId { get; set; }
public int DestinationGroupId { get; set; }
public string DestinationLookup { get; set; }
public DateTime CreatedDate { get; set; }
public string CreatedByUsername { get; set; }
public DateTime LastUpdatedDate { get; set; }
public string UpdatedByUsername { get; set; }
}
var rateSheetDetails = (from r in _Context.WholesaleRateSheet
join rateSheet in _Context.<tableName> on r.ResellerId equals rateSheet.ResellerId
where r.ResellerId == resellerId
select new { foo });
You're making a new type by doing this, as a combination of data from both tables. You can either define a model class and use something like
select new MyClass {
Foo = r.RateSheetMarkupId,
Bar = rateSheet.RateSheetName
}
Otherwise, no class definition is required. Simply using 'new' without a class will create an anonymous type with properties that match what you're selecting. The example here could be more precise if you share the entity names.
Altogether, going off your code:
public List<RateSheetModel> GetRateSheet(int resellerId)
{
var rateSheetDetails = (from r in _Context.WholesaleRateSheet
join m in _Context.RateSheetMarkup on r.ResellerId equals m.ResellerId
where r.ResellerId == resellerId
select new RateSheetModel {
ResellerId = r.ResellerId
RatesheetName = m.RatesheetName
};
return rateSheetDetails.ToList<RateSheetModel>;
}
public RateSheetModel { //dunno what this model looks like, but example
public int ResellerId {get; set;}
public string RatesheetName {get; set;}
}
For example I have these 2 Entities
public class Group
{
public int Id { get; set; }
public string Name { get; set; }
public string Email { get; set; }
public ICollection<EmployeeGroup> EmployeesGroups { get; set; }
}
public class ProcessState
{
public int Id { get; set; }
public string PendingEntity { get; set; }
public string ApprovingEntity { get; set; }
public string Message { get; set; }
public ICollection<Process> Processes { get; set; }
}
I would like to have
PendingEntity
ApprovingEntity
to be foreign keys to the Group Entity.
int PendingEntity - Group.Id
int ApprovingEntity - Group.Id
How can i describe this on my model?
I'm trying out OrmLite to see if I can replace Entity Framework in my projects. The speed is quite significant on simple queries. But I tried to map/reference a [1 to many- relation and read the documentation + examined the test code from the github page but without success. This is my example. Is there something I've forgot or should do to get it working like Entity Framework?
Example
// EF: returns +15.000 records + mapped > product.StockItems (slow)
dbContext.Products.Include(x => x.StockItems).ToList();
// OrmLite: returns +100.000 records (NO mapping > product.StockItems)
db.Select<Product>(db.From<Product>().Join<StockItem>());
// OrmLite: +15.000 separate requests to sql server (bad workarround + slow)
foreach (var product in db.Select<Product>())
{
// manual mapping
product.StockItems = db.Select<StockItem>(x => x.ProductId == product.Id);
}
Product.cs
public class Product
{
public int Id { get; set; }
public ProductType ProductType { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int DisplayOrder { get; set; }
public bool LimitedToStores { get; set; }
public string Sku { get; set; }
public decimal Price { get; set; }
public decimal OldPrice { get; set; }
public decimal SpecialPrice { get; set; }
public decimal DiscountPercentage { get; set; }
public DateTime? DateChanged { get; set; }
public DateTime? DateCreated { get; set; }
//...
[Reference]
public virtual IList<StockItem> StockItems { get; set; } = new List<StockItem>();
}
StockItem.cs
public class StockItem
{
public int Id {get; set;}
[References(typeof(Product))]
public int ProductId { get; set; }
public string Size { get; set; }
public int TotalStockQuantity { get; set; }
public string Gtin { get; set; }
public int DisplayOrder { get; set; }
// ...
[Reference]
public virtual Product Product { get; set; }
}
Ideally your POCOs/DTOs shouldn't use interfaces and you don't need to use virtual as ORM only populates your own POCOs (i.e. it doesn't create proxies of your models like other Heavy ORMs), I also prefer to use [AutoIncrement] for integer Ids (unless you need to populate specific Ids) so my Models would look like:
public class Product
{
[AutoIncrement]
public int Id { get; set; }
public ProductType ProductType { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public int DisplayOrder { get; set; }
public bool LimitedToStores { get; set; }
public string Sku { get; set; }
public decimal Price { get; set; }
public decimal OldPrice { get; set; }
public decimal SpecialPrice { get; set; }
public decimal DiscountPercentage { get; set; }
public DateTime? DateChanged { get; set; }
public DateTime? DateCreated { get; set; }
[Reference]
public List<StockItem> StockItems { get; set; }
}
public class StockItem
{
[AutoIncrement]
public int Id { get; set; }
[References(typeof(Product))]
public int ProductId { get; set; }
public string Size { get; set; }
public int TotalStockQuantity { get; set; }
public string Gtin { get; set; }
public int DisplayOrder { get; set; }
}
OrmLite's POCO References only populate 1-level deep and it's not a good idea to have cyclical relationships as they're not serializable so I'd remove the back reference on StockItems as it's not going to be populated.
You also need to use LoadSelect in order to query and return POCOs with references, so to return Product with their StockItem references you can just do:
db.LoadSelect<Product>();
You can also populate this manually with 2 queries by using Merge extension method to merge 2 disconnected record sets, e.g:
var q = db.From<Product>().Join<StockItem>();
var products = db.Select(q.SelectDistinct());
var stockItems = db.Select<StockItem>();
products.Merge(stockItems);
Which will merge Products with their StockItems which you can quickly see by running:
products.PrintDump();
Hi every one I want to save complex data using Entity Framework and C#. I have 2 classes Product and Order defined as follows
Product Class
public class Product
{
[Key]
public int Id { get; set; }
public string SKU_Code { get; set; }
public string Product_Name { get; set; }
public string Quantity { get; set; }
public string Price { get; set; }
public string Image { get; set; }
public DateTime Created_Date { get; set; }
public DateTime Modified_Date { get; set; }
}
Order Class
public class Order
{
[Key]
public long ID { get; set; }
public string Order_Id { get; set; }
public string Payment_Type { get; set; }
public string Customer_Name { get; set; }
public string Shipping_Address { get; set; }
public DateTime Order_Date { get; set; }
public DateTime Modified_Date { get; set; }
public bool Flag { get; set; }
public List<Product> ProductDetails { get; set; }
}
And I want to save data Order details and my piece of code is as follows.
public Order Add(Order odrerDetails)
{
using (var context = new EcommerceDBContext())
{
var MyOrder_Id = Helper.Random(7); //Generate random orderID from my class
foreach (var detail in odrerDetails.ProductDetails)
{
odrerDetails.Order_Id = MyOrder_Id;
odrerDetails.Quantity = Convert.ToInt32(detail.Quantity);
odrerDetails.Amount = Convert.ToDouble(detail.Price);
//Other Details
context.objOrderListing.Add(odrerDetails);
}
context.SaveChanges();
return odrerDetails;
}
}
This gives me perfect data but when it comes to context.SaveChanges(); it return's me error.
An error occurred while saving entities that do not expose foreign key properties for their relationships. The EntityEntries property will return null because a single entity cannot be identified as the source of the exception. Handling of exceptions while saving can be made easier by exposing foreign key properties in your entity types.
To me you domain model seems all wrong. The order should just be used for grouping, its a typical e-commerce scenario.
When you get a receipt of your purchases, you get one receipt with every Item and price listed next to it. Its considered as one order of multiple things, not multiple orders of multiple things.
Reading your last comment, you cant have multiple orders with the same order id. Try to understand the domain first before trying to solve it with code. Also,you have no notion of a Customer with an Order.
public class Product
{
[Key]
public int Id { get; set; }
public string SKU_Code { get; set; }
public string Product_Name { get; set; }
public string Price { get; set; }
public string Image { get; set; }
public DateTime Created_Date { get; set; }
public DateTime Modified_Date { get; set; }
}
public class Order
{
[Key]
public long ID { get; set; }
public string Order_Id { get; set; }
public string Payment_Type { get; set; }
public string Customer_Name { get; set; }
public string Shipping_Address { get; set; }
public DateTime Order_Date { get; set; }
public DateTime Modified_Date { get; set; }
public bool Flag { get; set; }
public List<OrderLineItem> Items { get; set; }
}
public class OrderLineItem
{
[Key]
public long ID { get; set; }
public long Order_Id { get; set; }
public long Product_Id {get; set;}
public int Quantity {get; set;}
}