I have to perform calculation on the data coming from database table - c#-3.0

services class
Here by using modelVms I am not getting column name, and how do return
variable v1, v2 with modelVms. Because I have to show v1& v2 value
on UI
public async Task<List<ProductivityAndLabourPerHectaresVM>> Get()
{
var models = await _unitOfWork.ProductivityAndLabourPerHectaresRepo.Get().ConfigureAwait(false);
if (models == null || models.Count <= 0)
return null;
var modelVms = _mapper.Map<List<ProductivityAndLabourPerHectaresVM>>(models);
if (modelVms == null || modelVms.Count <= 0) return null;
var v1=modelVMS.NoOfLabour/Area
var v2=modelVMS.Production/Area
return modelVms;
}

Related

Generic Entity Framework Pagination

I am trying to write a generic way to provide pagination on my Link query to my MySQL database. However this required me to have a generic way to where, as the field used may differ from table to table. The issue i am facing it that Linq can't translate my generic types. Are there a way to do this that would work with Linq?
public static class PaginationExtentions {
public static async Task<PaginationResult<T>> Pagination<T, J>(this DbSet<J> dbSet, Pagination pagination, Func<IQueryable<J>, IQueryable<T>>? select) where J : class {
bool previousPage = false;
bool nextPage = false;
string startCursor = null;
string endCursor = null;
var property = typeof(J).GetProperty(pagination.SortBy);
string after = pagination.After != null ? Base64Decode(pagination.After) : null;
bool backwardMode = after != null && after.ToLower().StartsWith("prev__");
string cursor = after != null ? after.Split("__", 2).Last() : null;
List<J> items;
if (cursor == null) {
items = await (from s in dbSet
orderby GetPropertyValue<J, string>(s, pagination.SortBy) ascending
select s).Take(pagination.First)
.ToListAsync();
}
else if (backwardMode) {
items = await (from subject in (
from s in dbSet
where string.Compare( (string?)property.GetValue(s), cursor) < 0
orderby (string?)property.GetValue(s) descending
select s).Take(pagination.First)
orderby (string?)property.GetValue(subject) ascending
select subject).ToListAsync();
}
else {
items = await (from s in dbSet
where string.Compare((string?)property.GetValue(s), cursor) > 0
orderby GetPropertyValue<J, string>(s, pagination.SortBy) ascending
select s).Take(pagination.First)
.ToListAsync();
}
previousPage = await dbSet.Where(s => string.Compare((string?)property.GetValue(s), cursor) < 0).AnyAsync();
nextPage = items.Count == 0 ? false : await dbSet.Where(s => string.Compare((string?)property.GetValue(s), (string?)property.GetValue(items.Last())) > 0).AnyAsync();
var backwardsCursor = !previousPage ? null : "prev__" + cursor;
var forwardsCursor = !nextPage ? null : items.Count > 0 ? "next__" + (string?)property.GetValue(items.Last()) : null;
return new PaginationResult<T>() {
Items = select(items.AsQueryable()).ToList(),
TotalCount = await dbSet.CountAsync(),
HasPreviousPage = previousPage,
HasNextPage = nextPage,
StartCusor = Base64Encode(backwardsCursor),
EndCursor = Base64Encode(forwardsCursor)
};
}
private static U GetPropertyValue<T, U>(T obj, string propertyName) {
return (U)obj.GetType().GetProperty(propertyName).GetValue(obj, null);
}
public static string Base64Encode(string plainText) {
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(plainText);
return System.Convert.ToBase64String(plainTextBytes);
}
public static string Base64Decode(string base64EncodedData) {
var base64EncodedBytes = System.Convert.FromBase64String(base64EncodedData);
return System.Text.Encoding.UTF8.GetString(base64EncodedBytes);
}
}

Postgres function is not working/calling in hosted web project

I have created an ASP.Net Core Web App (MVC) Project which in turns call Web Api for calling the database for getting the values and posting the values. The database used is Postgres. I have written a Postgres function to populate values for a report Day Book. When I run the project through visual studio it works fine. Then I have hosted the project. When I login through hosted ip address and calling the report function returns no values and the reports showing no values.
The Postgres function is given below
CREATE OR REPLACE FUNCTION public.day_book(
d1 date,
d2 date,
cid integer)
RETURNS TABLE(roworder integer, guid uuid, tbl1 text, date1 timestamp without time zone, credit real, debit real, description1 text, credit1 real, debit1 real)
LANGUAGE 'plpgsql'
COST 100
VOLATILE
ROWS 1000
AS $BODY$
BEGIN
RETURN QUERY
SELECT db1."roworder",db1."guid",db1."tbl1",db1."date1",db1."credit",db1."debit",
db1."description1",db1."credit1",db1."debit1"
from "tbldaybook1" as db1 order by db1."date1",db1."roworder";
END;
$BODY$;
The MVC controller method that calls the API controller method is given below
public async Task<JsonResult> GetDayBook(DateTime FromDate, DateTime ToDate)
{
ClaimsPrincipal currentUser = this.User;
var currentUserId = Convert.ToInt32(currentUser.FindFirst("UserId").Value);
var ChurchId = Convert.ToInt32(currentUser.FindFirst("ChurchId").Value);
var Role = currentUser.FindFirst(ClaimTypes.Role).Value;
var isSuperAdmin = Convert.ToBoolean(currentUser.FindFirst("IsSuperAdmin").Value);
var d11 = FromDate.ToString("dd-MM-yyyy");
var d22 = ToDate.ToString("dd-MM-yyyy");
int cid = ChurchId;
List<RptDayBook> daybook = new List<RptDayBook>();
HttpClient client = api.Initial();
HttpResponseMessage responseTask = await client.GetAsync("reports/GetDayBook/" + d11 + "/" + d22 + "/" + cid);
if (responseTask.IsSuccessStatusCode)
{
var readTask = responseTask.Content.ReadAsStringAsync().Result;
daybook = JsonConvert.DeserializeObject<List<RptDayBook>>(readTask);
}
return Json(daybook);
}
The below API method connects to the Postgres database and call the function
[HttpGet("GetDayBook/{d11}/{d22}/{cid}")]
public IEnumerable<RptDayBook> GetDayBook(string d11, string d22, int cid)
{
using (var command = db.Database.GetDbConnection().CreateCommand())
{
DateTime d1 = Convert.ToDateTime(d11);
DateTime d2 = Convert.ToDateTime(d22).AddDays(1);
command.CommandType = CommandType.StoredProcedure;
command.CommandText = "day_book";
command.Parameters.Add(new Npgsql.NpgsqlParameter("d1", NpgsqlTypes.NpgsqlDbType.Date)
{ Value = d1 });
command.Parameters.Add(new Npgsql.NpgsqlParameter("d2", NpgsqlTypes.NpgsqlDbType.Date)
{ Value = d2 });
command.Parameters.Add(new Npgsql.NpgsqlParameter("cid", NpgsqlTypes.NpgsqlDbType.Integer)
{ Value = cid });
if (command.Connection.State == ConnectionState.Closed)
command.Connection.Open();
List<object[]> result = new List<object[]>();
var res = command.ExecuteReader();
if (res.HasRows)
{
while (res.Read())
{
var values = new object[res.FieldCount];
for (int i = 0; i < res.FieldCount; i++)
{
if (i == 4 || i == 5 || i == 7 || i == 8)
{
values[i] = res[i] == DBNull.Value ? 0 : Convert.ToDouble(res[i]);
}
else
{
values[i] = res[i];
}
}
result.Add(values);
}
}
List<RptDayBook> rpt = new List<RptDayBook>();
foreach (var item in result)
{
RptDayBook rptDayBook = new RptDayBook();
rptDayBook.roworder = (int)item[0];
rptDayBook.GUID = (Guid)item[1];
rptDayBook.tbl1 = (string)item[2];
rptDayBook.date1 = (DateTime)item[3];
rptDayBook.credit = item[4] == DBNull.Value ? 0 : Convert.ToDouble(item[4]);
rptDayBook.debit = item[5] == DBNull.Value ? 0 : Convert.ToDouble(item[5]);
rptDayBook.Description1 = (string)item[6];
rptDayBook.credit1 = item[7] == DBNull.Value ? 0 : Convert.ToDouble(item[7]);
rptDayBook.debit1 = item[8] == DBNull.Value ? 0 : Convert.ToDouble(item[8]);
rpt.Add(rptDayBook);
}
return rpt;
}
}
What will be the issue? Is it either the function is not calling or function can't return values?
It is the issue while converting the datetime in the API.
Change the code from
DateTime d1 = Convert.ToDateTime(d11);
to
DateTime d1 = DateTime.ParseExact(d11, "dd-MM-yyyy", CultureInfo.InvariantCulture);
Also do the same in the next line also.

Only Update Entity (Parent or children) if Property Values Have Changed with EF

As I build a project with Entity Framework 6 (using EF for the first time), I noticed that when I only Update the relationships of an Entity, EF updates the main Entity too.
I can tell this is happening because I'm using System Versioned tables on Sql Server 2017.
This is a made up scenario, but most of the concept is here.
public async Task<ActionResult> Edit([Bind(Include="Id,Name,LocationTimes")] LocationViewModel locationVM) {
if (ModelState.IsValid) {
var location = await _db.Locations.FirstOrDefaultAsync(l => l.Id == locationsViewModel.Id && l.UserId == UserId);
if (location == null) {
return HttpNotFound();
}
location.Name = locationsViewModel.Name;
// ... other properties
foreach (var day in locationsViewModel.LocationTimes.Days) {
var time = new Time {
Day = day.Day,
OpenTime = day.OpenTime,
CloseTime = day.CloseTime,
};
// Find current Time or keep newly created
time = await time.FindByTimeAsync(time, _db) ?? time;
// Find LocationTime with same day
var locationTime = location.LocationTimes.FirstOrDefault(lt => lt.Time.Day == day.Day);
// If all times are the same, skip (continue)
if (locationTime != null && locationTime.Time.OpenTime == time.OpenTime && locationTime.Time.CloseTime == time.CloseTime)
continue;
if (locationTime != null && (locationTime.Time.OpenTime != time.OpenTime || locationTime.Time.CloseTime != time.CloseTime)) {
// Remove, At least one of the Times do not match
locationTime.Time = time;
_db.Entry(locationTime).State = EntityState.Modified;
} else {
location.LocationTimes.Add(new LocationTime {
Location = location,
Time = time,
});
}
}
_db.Entry(location).State = EntityState.Modified;
await _db.SaveChangesAsync();
return RedirectToAction("Index");
}
}
I assume, that by marking the entire Entity as Modified, EF will call the update statement.
How can I avoid an UPDATE to the parent Entity, if no properties have changed on the parent, but still Add/Update the child relationships?
I assume I have to check that each property has not changed and therefore I should not be setting location state to Modified, but how would I handle the newly added Times?
Update #1
So I tried what I mentioned and it works, but is this the correct way to do this?
public async Task<ActionResult> Edit([Bind(Include="Id,Name,LocationTimes")] LocationViewModel locationVM) {
if (ModelState.IsValid) {
var location = await _db.Locations.FirstOrDefaultAsync(l => l.Id == locationsViewModel.Id && l.UserId == UserId);
if (location == null) {
return HttpNotFound();
}
/*******************
This is new part
*******************/
if (
location.Name != locationsViewModel.Name
// || ... test other properties
) {
location.Name = locationsViewModel.Name;
// ... other properties
_db.Entry(location).State = EntityState.Modified;
} else {
_db.Entry(location).State = EntityState.Unchanged;
}
/*******************/
foreach (var day in locationsViewModel.LocationTimes.Days) {
var time = new Time {
Day = day.Day,
OpenTime = day.OpenTime,
CloseTime = day.CloseTime,
};
// Find current Time or keep newly created
time = await time.FindByTimeAsync(time, _db) ?? time;
// Find LocationTime with same day
var locationTime = location.LocationTimes.FirstOrDefault(lt => lt.Time.Day == day.Day);
// If all times are the same, skip (continue)
if (locationTime != null && locationTime.Time.OpenTime == time.OpenTime && locationTime.Time.CloseTime == time.CloseTime)
continue;
if (locationTime != null && (locationTime.Time.OpenTime != time.OpenTime || locationTime.Time.CloseTime != time.CloseTime)) {
// Remove, At least one of the Times do not match
locationTime.Time = time;
_db.Entry(locationTime).State = EntityState.Modified;
} else {
location.LocationTimes.Add(new LocationTime {
Location = location,
Time = time,
});
}
}
/* removed, added above */
//_db.Entry(location).State = EntityState.Modified;
await _db.SaveChangesAsync();
return RedirectToAction("Index");
}
}
So after trial and error, I guess I misunderstood how EF handles the EntityState. I though if a child was Modified, you had to set the parent as Modified as well.
Gladly, that's not the case and the code below works as desired.
public async Task<ActionResult> Edit([Bind(Include="Id,Name,LocationTimes")] LocationViewModel locationVM) {
if (ModelState.IsValid) {
var location = await _db.Locations.FirstOrDefaultAsync(l => l.Id == locationsViewModel.Id && l.UserId == UserId);
if (location == null) {
return HttpNotFound();
}
/*******************
This is new part
check if at least one property was changed
*******************/
if (
location.Name != locationsViewModel.Name
|| location.Ref != locationsViewModel.Ref
// || ... test other properties
) {
location.Name = locationsViewModel.Name;
location.Ref = locationsViewModel.Ref;
// ... other properties
// Tell EF that the Entity has been modified (probably not needed, but just in case)
_db.Entry(location).State = EntityState.Modified;
} else {
// Tell EF that the Entity has *NOT* been modified
_db.Entry(location).State = EntityState.Unchanged;
}
/*******************/
foreach (var day in locationsViewModel.LocationTimes.Days) {
var time = new Time {
Day = day.Day,
OpenTime = day.OpenTime,
CloseTime = day.CloseTime,
};
// Find current Time or keep newly created
time = await time.FindByTimeAsync(time, _db) ?? time;
// Find LocationTime with same day
var locationTime = location.LocationTimes.FirstOrDefault(lt => lt.Time.Day == day.Day);
// If all times are the same, skip (continue)
if (locationTime != null && locationTime.Time.OpenTime == time.OpenTime && locationTime.Time.CloseTime == time.CloseTime)
continue;
if (locationTime != null && (locationTime.Time.OpenTime != time.OpenTime || locationTime.Time.CloseTime != time.CloseTime)) {
// Remove, At least one of the Times do not match
locationTime.Time = time;
_db.Entry(locationTime).State = EntityState.Modified;
} else {
location.LocationTimes.Add(new LocationTime {
Location = location,
Time = time,
});
}
}
/* removed, added above */
//_db.Entry(location).State = EntityState.Modified;
await _db.SaveChangesAsync();
return RedirectToAction("Index");
}
}

Some part of your SQL statement is nested too deeply

I have the following code
[WebGet]
public Bid GetHighestBidInOpenAuctions(int auctionEventId)
{
var auctionEvent = CurrentDataSource.AuctionEvents.Where(x => x.Id == auctionEventId).FirstOrDefault();
var auctionIds = CurrentDataSource.Auctions.Where(x => x.AuctionEventId == auctionEventId && x.Ends > DateTime.UtcNow).Select(x => x.Id).ToList();
var bids = CurrentDataSource.Bids.Where(x => auctionIds.Any(t => t == x.AuctionId));
// If the auction Event has not yet started or there are no bids then show auction with high pre-sale estimate.
if (bids.Count() == 0 || auctionEvent.Starts > DateTime.UtcNow)
{
return null;
}
var highestBid = bids.Where(b => b.IsAutobid == false).OrderByDescending(b => b.Amount).FirstOrDefault();
return highestBid;
}
This line throws the below exception
if (bids.Count() == 0 || auctionEvent.Starts > DateTime.UtcNow)
Some part of your SQL statement is nested too deeply. Rewrite the query or break it up into smaller queries.
What's wrong?
EDIT
I have tried doing this
IQueryable<Bid> bids = CurrentDataSource.Bids.Where(b => 0 == 1);
foreach(var auctionId in auctionIds)
{
int id = auctionId;
bids = bids.Union(CurrentDataSource.Bids.Where(b => b.AuctionId == id));
}
But I still get the same error.
Rather than using a subquery, try replacing the bid query with:
var bids = CurrentDataSource.Bids.Where(b => b.AuctionEventId == auctionEventId
&& b.Auction.AuctionEvent.Starts > DateTime.UtcNow
&& b.Auction.Ends > DateTime.UtcNow);
if (bids.Count() == 0
{
return null;
}
It seems when you have too many things in your database then you will get this error (auctionIds in my case) because the generated sql will be too deeply nested. To solve this I came up with this solution. If anyone can do better then do. I'm posting this because someone may have this error in the future and if they do, in the absence of a better solution this might help them.
[WebGet]
public Bid GetHighestBidInOpenAuctions(int auctionEventId)
{
/*
* This method contains a hack that was put in under tight time constraints. The query to
* get bids for all open auctions used to fail when we had a large number of open auctions.
* In this implementation we have fixed this by splitting the open auctions into groups of 20
* and running the query on those 20 auctions and then combining the results.
*/
const int auctionIdSegmentSize = 20;
var auctionEvent = CurrentDataSource.AuctionEvents.Where(x => x.Id == auctionEventId).FirstOrDefault();
var auctionIds = CurrentDataSource.Auctions.Where(x => x.AuctionEventId == auctionEventId && x.Ends > DateTime.UtcNow).Select(x => x.Id).ToList();
int numberOfSegments = auctionIds.Count/auctionIdSegmentSize;
if (auctionIds.Count % auctionIdSegmentSize != 0)
numberOfSegments++;
var bidsList = new List<IQueryable<Bid>>();
for (int i = 0; i < numberOfSegments; i++)
{
int start = i*auctionIdSegmentSize;
int end;
if (i == numberOfSegments - 1)
{
end = auctionIds.Count - 1;
}
else
{
end = ((i + 1)*auctionIdSegmentSize) - 1;
}
var subList = auctionIds.GetRange(start, (end - start) + 1);
bidsList.Add(CurrentDataSource.Bids.Where(b => subList.Any(id => id == b.AuctionId)));
}
// If the auction Event has not yet started or there are no bids then show auction with high pre-sale estimate.
if (IsBidsCountZero(bidsList) || auctionEvent.Starts > DateTime.UtcNow)
{
return null;
}
var highestBid = FindHighestBid(bidsList);
return highestBid;
}
private Bid FindHighestBid(List<IQueryable<Bid>> bidsList)
{
var bids = new List<Bid>();
foreach (var list in bidsList)
{
bids.Add(list.Where(b => b.IsAutobid == false).OrderByDescending(b => b.Amount).FirstOrDefault());
}
bids.RemoveAll(b => b == null);
if (bids.Count == 0)
return null;
bids.Sort(BidComparison);
return bids[0];
}
private int BidComparison(Bid bid1, Bid bid2)
{
if (bid1.Amount < bid2.Amount)
return 1;
if (bid1.Amount > bid2.Amount)
return -1;
return 0;
}
private bool IsBidsCountZero(List<IQueryable<Bid>> bidsList)
{
int count = 0;
foreach (var list in bidsList)
{
count += list.Count();
}
return count == 0;
}
The problem is with auctionIds.Any(t => t == x.AuctionId) where EF cannot create a correct query. You can change it to:
var bids = CurrentDataSource.Bids.Where(x => auctionIds.Contains(x.AuctionId));
Where EF can convert auctionIds to a collection and pass to DB.

How to calculate the color based on given fgColor indexed

I am working on Open XML,
<x:fill>
<x:patternFill patternType="solid">
<x:fgColor indexed="46" />
<x:bgColor indexed="64" />
</x:patternFill>
</x:fill>
Above is a office 2007 document that converted from office 2003.
According to http://msdn.microsoft.com/en-us/library/documentformat.openxml.spreadsheet.foregroundcolor.aspx
Indexed attributes only used for backward compatibility purposes.
Above is my code, how to calculate the #Hex Color Code for indexed = 46?
I made this class for myself. Hope I save someone some trouble
public class IndexedColours
{
static Dictionary<string, string> Data;
IndexedColours()
{
if(Data == null || Data.Count == 0)
{
Data = new Dictionary<string, string>();
Data.Add("0", "000000");
Data.Add("1", "FFFFFF");
Data.Add("2", "FF0000");
Data.Add("3", "00FF00");
Data.Add("4", "0000FF");
Data.Add("5", "FFFF00");
Data.Add("6", "FF00FF");
Data.Add("7", "00FFFF");
Data.Add("8", "000000");
Data.Add("9", "FFFFFF");
Data.Add("10", "FF0000");
Data.Add("11", "00FF00");
Data.Add("12", "0000FF");
Data.Add("13", "FFFF00");
Data.Add("14", "FF00FF");
Data.Add("15", "00FFFF");
Data.Add("16", "800000");
Data.Add("17", "008000");
Data.Add("18", "000080");
Data.Add("19", "808000");
Data.Add("20", "800080");
Data.Add("21", "008080");
Data.Add("22", "C0C0C0");
Data.Add("23", "808080");
Data.Add("24", "9999FF");
Data.Add("25", "993366");
Data.Add("26", "FFFFCC");
Data.Add("27", "CCFFFF");
Data.Add("28", "660066");
Data.Add("29", "FF8080");
Data.Add("30", "0066CC");
Data.Add("31", "CCCCFF");
Data.Add("32", "000080");
Data.Add("33", "FF00FF");
Data.Add("34", "FFFF00");
Data.Add("35", "00FFFF");
Data.Add("36", "800080");
Data.Add("37", "800000");
Data.Add("38", "008080");
Data.Add("39", "0000FF");
Data.Add("40", "00CCFF");
Data.Add("41", "CCFFFF");
Data.Add("42", "CCFFCC");
Data.Add("43", "FFFF99");
Data.Add("44", "99CCFF");
Data.Add("45", "FF99CC");
Data.Add("46", "CC99FF");
Data.Add("47", "FFCC99");
Data.Add("48", "3366FF");
Data.Add("49", "33CCCC");
Data.Add("50", "99CC00");
Data.Add("51", "FFCC00");
Data.Add("52", "FF9900");
Data.Add("53", "FF6600");
Data.Add("54", "666699");
Data.Add("55", "969696");
Data.Add("56", "003366");
Data.Add("57", "339966");
Data.Add("58", "003300");
Data.Add("59", "333300");
Data.Add("60", "993300");
Data.Add("61", "993366");
Data.Add("62", "333399");
Data.Add("63", "333333");
}
}
public static string GetIndexColour(string Index)
{
var d = new IndexedColours();
var res = "";
var exist = Data.TryGetValue(Index, out res);
if (exist)
return res;
else return "000000";
}
}
Method to use the above code:
public static string GetCellColour(this Cell cell, SpreadsheetDocument d)
{
if (cell != null && cell.StyleIndex != null)
{
var valcell = cell;
var styles = d.WorkbookPart.WorkbookStylesPart;
var ss = styles.Stylesheet;
var formats = ss.CellFormats;
var cf = (CellFormat)formats.ElementAt((int)valcell.StyleIndex.Value);
var fill = (Fill)styles.Stylesheet.Fills.ChildElements[(int)cf.FillId.Value];
var fgc = fill.PatternFill.ForegroundColor;
var cl = fgc == null || fgc.Rgb == null ? "FFFFFF" : fgc.Rgb.Value.Remove(0, 2);
if (fgc != null && fgc.Indexed != null && fgc.Indexed.HasValue)
{
cl = IndexedColours.GetIndexColour(fgc.Indexed.Value.ToString());
}
return cl;
}
else return "FFFFFF";
}
Solved my problem, there is color indexes online. just search for it.