Dapper map subquery value to property - c#

I'm using Dapper to fetch and map data. I've the following query and relevant class.
SELECT pinv.* , sp.SupplierId,sp.SupplierName,sp.Contact1,sp.SupplierAddress,ac.AccountId,ac.AccountName,
(Select Count(*) from ReturnInvoices rinv Where rinv.InvoiceId = pinv.PurchaseInvoiceId) as ReturnInvoicesCount
FROM PurchaseInvoices pinv
LEFT JOIN Suppliers sp ON sp.SupplierId = pinv.SupplierId
LEFT JOIN Accounts ac on ac.AccountId = pinv.AccountId
And the class.
public class PurchaseInvoice
{
public int PurchaseInvoiceId { get; set; }
public int PurchaseOrderId { get; set; }
public string PurchaseInvoiceType { get; set; }
public int SupplierId { get; set; }
public int AccountId { get; set; }
public int ReceiptNumber { get; set; }
public int ReturnInvoicesCount { get; set; } // to map ReturnInvoiceCount by SubQuery
public DateTime PromisedDate { get; set; }
public DateTime InvoiceDate { get; set; }
public decimal InvoiceQuantity { get; set; }
public decimal Discount { get; set; }
public decimal Tax { get; set; }
public decimal ShippingCharges { get; set; }
public decimal Surcharge { get; set; }
public string PaymentMode { get; set; }
public decimal SubTotal { get; set; }
public decimal TotalPayment { get; set; }
public decimal AmountPaid { get; set; }
public decimal AmountRemaining { get; set; }
public string Comments { get; set; }
public string Status { get; set; }
public DateTime UpdatedDate { get; set; }
public Supplier Supplier { get; set; }
public ProductReceived ProductReceived { get; set; }
public Account Account { get; set; }
}
I'm not sharing other classes because they are not relevant. Now, if i run above query, I get perfect results as excepted. After fetching results the dapper returns all data just fine but ReturnInvoicesCount is not mapped (or idk something else is problem). This is how I'm using dapper.
using (SqlConnection connection = new SqlConnection(_conString))
{
var query = QueryHelper.GetPurchaseInvoicesQuery(start, end, simpleSearchText, searchTokensList);
// ignore above line, just getting query with parameters etc
var data = await connection.QueryAsync<PurchaseInvoice, Supplier, Account>(query.Query,
query.queryParams, splitOn: "SupplierId,AccountId");
return data;
}
As i said, I get correct result mapped except field ReturnInvoicesCount which is 0. While on server as can be seen ReturnInvoiceCount have a value.

You have splits on SupplierId (Maps to Supplier) and AccountId (Maps to Account). The problem is that ReturnInvoicesCount is at the wrong column position to be correctly mapped. Currently, you tell dapper that ReturnInvoicesCount belongs to Account.
Since ReturnInvoicesCount belongs to PurchaseInvoice you have to move it before SupplierId.

Related

EF Include is not working! returning null in a 1 to many relationship

i am trying to display a list of cities with a country, a 1 to many relation.
I created the models for both of them:
City model
[Key]
public int ID_Cidade { get; set;
public int ID_Pais { get; set; }
public RH_Pais Pais { get; set; }
public string Nome { get; set; }
public Boolean Capital { get; set; }
public DateTime SysStartTime { get; set; }
public DateTime SysEndTime { get; set; }
public string Autor { get; set; }
public int OrdemCidade { get; set; }
public List<RH_Escritorios> Escritorios { get; set; }
Country model
[Key]
public int ID_Pais { get; set; }
public int ID_Moeda { get; set; }
public RH_Moeda Moeda { get; set; }
public string Nome { get; set; }
public string Nome_completo { get; set; }
public DateTime SysStartTime { get; set; }
public DateTime SysEndTime { get; set; }
public string Autor { get; set; }
public int OrdemPais { get; set; }
public List<RH_Cidades> Cidades { get; set; }
public List<RH_Idioma_Pais> Idiomas { get; set; }
and then i used fluent API to create the relationship
modelBuilder.Entity<RH_Cidades>()
.HasOne(m => m.Pais)
.WithMany(m => m.Cidades)
.HasForeignKey(m => m.ID_Pais);
and somehow when i generate the controller with EF, and i go to see the cities it causes a null error... this is because it has a include of the country when im trying to get the cities..
var rH_EntitiesContext = _context.RH_Cidades.Include(r => r.Pais).ToList();
The most annoying part is that i have the exact same situation in another relationship, with 1 to many and the include and it works perfectly!!
I have read and read my code for hours by now and i cannot see why the Include is giving me that error when in the offices controller with the same situation works...
Any help is appreciated!!!

Retrieving data from a different connection after logging in?

I am building a holiday tracking website.
I have two data connections in my mvc application.
DeafultConnection which contains aspnetusers which I am using for user logins and Registrations.
Then LotusWorksEntities which I am using to track Employee details such as holiday requests, hours taking etc.
In DefaultConnections under aspnetusers, there's a column for email.
In LotusWorksEntitles under Employee Table, there's also a column for email.
On my Admin view page, I have a list of all Employees which has a column for Site.
I want Admins who have been assigned certain sites to only see employees from those assigned sites.
I have done this manually by
public ActionResult Index()
{
var employees = db.Employees.Include(e => e.Area).Include(e => e.Discipline).Include(e => e.Shift).Include(e => e.Site).Where(e => e.SiteID == 2);
return View(employees.ToList());
}
Is there a way that I could connect these two connections, so that when an admin logs in, it knows what site they've been assigned to and displays those employees under that site.
Here are my models:
public partial class Employee
{
public int EmployeeID { get; set; }
public string FullName { get; set; }
public string Email { get; set; }
public string Password { get; set; }
public System.DateTime StartDate { get; set; }
public int RoleID { get; set; }
public int ShiftID { get; set; }
public int AreaID { get; set; }
public int DisciplineID { get; set; }
public int SiteID { get; set; }
public int ALCategory { get; set; }
public int HoursTaken { get; set; }
public Nullable<int> AwardedLeave { get; set; }
public Nullable<int> TotalHoursThisYear { get; set; }
public int HoursCarriedForward { get; set; }
public Nullable<int> EntitlementRemainingThisYear { get; set; }
public string Comments { get; set; }
public int SickLeaveTaken { get; set; }
public Nullable<int> SickLeaveEntitlement { get; set; }
public Nullable<int> SickLeaveEntitlementRemaining { get; set; }
public int StudyLeaveEntitlement { get; set; }
public int StudyLeaveTaken { get; set; }
public Nullable<int> StudyLeaveRemaining { get; set; }
public int ExamLeaveTaken { get; set; }
public int ForceMajeure { get; set; }
public int BereavementLeaveTaken { get; set; }
public int MaternityLeaveTaken { get; set; }
public int ParentalLeaveTaken { get; set; }
public int AdoptionLeaveTaken { get; set; }
public string ManagerEmail { get; set; }
public string AreaManagerEmail { get; set; }
public virtual Area Area { get; set; }
public virtual Discipline Discipline { get; set; }
public virtual Shift Shift { get; set; }
public virtual Site Site { get; set; }
}
Then my Site Model is:
public partial class Site
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Site()
{
this.Employees = new HashSet<Employee>();
}
public int SiteID { get; set; }
public string SiteName { get; set; }
public string SiteManager { get; set; }
public string SiteDelegate { get; set; }
public string SiteAdmin { get; set; }
public string SiteLocation { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Employee> Employees { get; set; }
}
Employee Table and Site Table are connected through a foreign key.
Not completely understood which two connections you have is it database connection you are talking about?
But anyways you can use Linq joins to connect two separate list of objects in C#. filter data. Basically your two list should have some relation for join to work.
Here it is explained how to join two list in memory.

Entity Framework multiple object relations to same column

I have couple of entities such as Customer, Vendors, Employee and I have another entity to handle Transaction Head, check definition here:
public class TransactionHead
{
public string DocumentNo { get; set; }
public DocumentType TransactionType { get; set; }
public Location From { get; set; }
public object To { get; set; }//customer, supplier, location, employee "will have a discount table "
public DateTime DocumentDate { get; set; }
public float GrossAmount { get; set; }
public float TotalDiscount { get; set; }
public float NetAmount { get; set; }
public int DetailRowCount { get; set; }
public bool IsActive { get; set; }
public bool IsDeleted { get; set; }
public User Created { get; set; }
public User Updated { get; set; }
public User Approved { get; set; }
public DocumentStatus DocumentStatus { get; set; }
public string ApprovalRemark { get; set; }
public string DocumentRemark { get; set; }
public DateTime CreatedTimeStamp { get; set; }
public DateTime UpdatedTimeStamp { get; set; }
}
And now when I create migration, it automatically ignores the To property from TransactionHead entity. So what is the solution?
Thanks
No. EF doesn't support this because it would require dynamic column type in the database. the object property that EF will always ignore. you can find more information about complex type in EF in this link.

Sum Related Collection By Property in Entity Framework (Lazy Loaded)

I am in need of some assistance with an Entity Framework query. I have the following entities:
public class Invoice
{
public Guid Id { get; set; }
public DateTime CreateDate { get; set; }
[ForeignKey("CreatedById")]
public virtual ApplicationUser CreatedBy { get; set; }
public Guid CreatedById { get; set; }
public bool Approved { get; set; }
public virtual ICollection<InvoiceDetail> Details { get; set; }
}
public class InvoiceDetail
{
public Guid Id { get; set; }
[ForeignKey("InvoiceId")]
public virtual Invoice Invoice { get; set; }
public Guid InvoiceId { get; set; }
public string Item { get; set; }
public string Description { get; set; }
public decimal Quantity { get; set; }
public decimal UnitCost { get; set; }
public decimal Discount { get; set; }
}
I am trying to sum the total of all the items where an invoice is Approved. The problem I'm having is the syntax on getting to the InvoiceDetail level once I filter for the Approved = 1:
var myInvoices = context.Invoices.Where(i => i.CreatedById == userId).Include(i => i.CreatedBy).Include(i => i.Details);
var approvedTotal = myInvoices.Where(i => i.Approved == 1).Select([GET TO DETAILS???]);
// my goal is to get the following sum for each detail for all of the approved invoices:
// ((d.Quantity * d.UnitCost) - d.Discount)
Assuming that you wanted to get a sum total of all details after the given calculation had been performed you could do something like this:
var approvedTotal = invoices.Where(invoice => invoice.Approved)
.Select(invoice => invoice.Details.Sum(detail => ((detail.Quantity * detail.UnitCost) - detail.Discount)));
So this gives you one total per invoice.

String or binary data would be truncated.The statement has been terminated while removing data

I have a PriceId and I get some PriceGaranties by it and I am trying to delete PriceGaranties by updating Price and see this error.
Here is the code:
public void DeletePriceGaranties(int priceId)
{
var deletedPriceGaranties = context.PriceGaranties.Where(p => p.PriceId == priceId).ToList();
foreach (var priceGaranty in deletedPriceGaranties)
{
context.PriceGaranties.Remove(priceGaranty);
context.SaveChanges();
}
}
The error is:
String or binary data would be truncated. The statement has been
terminated.
Update
Here are the models:
public class Price
{
public int PriceId { get; set; }
public int ProductId { get; set; }
public int ClassId { get; set; }
public int ClassPartnerId { get; set; }
public int UserId { get; set; }
public decimal Cost { get; set; }
public string Url { get; set; }
public string Description { get; set; }
public DateTime LastUpdate { get; set; }
public bool Enable { get; set; }
public int CostTypeId { get; set; }
public int Value { get; set; }
public Class Class { get; set; }
public Product Product { get; set; }
public User User { get; set; }
public List<OldPrice> OldPrices { get; set; }
public List<PriceColor> PriceColors { get; set; }
public List<PriceGaranty> PriceGaranties { get; set; }
public ClassPartner ClassPartner { get; set; }
}
public class PriceGaranty
{
public int PriceGarantyId { get; set; }
public int PriceId { get; set; }
public int GarantyId { get; set; }
public Comparing.Model.Price.Price Price { get; set; }
}
And all of string types are nvarchar(MAX).
You have specified the length of the string in your database to be shorter than what you are trying to add to it. E.g. you may have set a varchar length in your database to be of length 10 but the string you want to add is 11, 15, 20 etc characters. The database doesnt know what to do with it so it just cuts off the excess characters. Try setting the field length in your database to a larger length.

Categories