Limit 1000 Records from CosmosDB Query - c#

I need to limit the results of a query to CosmosDB to 1000 records, I am trying to set the feed iterator to exit once the result list hits 1000 but right now it is stopping after 100 records. Here is my current code:
public async Task<IEnumerable<AS2InboundLogRecord>> RetrieveInboundLogs(string partitionKeyName, DateTime startDate, DateTime endDate)
{
var inboundLogs = new List<AS2InboundLogRecord>();
string continuationToken = null;
int itemLimit = 1000;
QueryRequestOptions requestOptions = new QueryRequestOptions()
{
MaxItemCount = 100
};
using (FeedIterator<AS2InboundLogRecord> setIterator = dbContainer.GetItemLinqQueryable<AS2InboundLogRecord>(true, continuationToken, requestOptions)
.Where(x => (x.PartitionKey == partitionKeyName || partitionKeyName == null) &&
(x.MessageDate >= startDate) &&
(x.MessageDate <= endDate))
.ToFeedIterator())
{
while (setIterator.HasMoreResults)
{
FeedResponse<AS2InboundLogRecord> response = await setIterator.ReadNextAsync();
inboundLogs.AddRange(response);
if (response.Count >= itemLimit) { break; }
}
Console.WriteLine(inboundLogs.Count());
return inboundLogs.OrderByDescending(x => x.MessageDate);
};
}
Any input would be appricated, thanks

I think you have to correct two things:
First: you set limitCount to 100 sound like it just fetch only 100 records , if this limit fetch count set it to 1000 otherwise goto Second phrase.
Second: your if condition may not work because you compare response.Count while inboundLogs.Count should be compare.
Correction:
public async Task<IEnumerable<AS2InboundLogRecord>> RetrieveInboundLogs(string partitionKeyName, DateTime startDate, DateTime endDate)
{
var inboundLogs = new List<AS2InboundLogRecord>();
string continuationToken = null;
int itemLimit = 1000;
QueryRequestOptions requestOptions = new QueryRequestOptions()
{
MaxItemCount = 10000
};
using (FeedIterator<AS2InboundLogRecord> setIterator = dbContainer.GetItemLinqQueryable<AS2InboundLogRecord>(true, continuationToken, requestOptions)
.Where(x => (x.PartitionKey == partitionKeyName || partitionKeyName == null) &&
(x.MessageDate >= startDate) &&
(x.MessageDate <= endDate))
.ToFeedIterator())
{
while (setIterator.HasMoreResults)
{
FeedResponse<AS2InboundLogRecord> response = await setIterator.ReadNextAsync();
inboundLogs.AddRange(response);
if (inboundLogs.Count >= itemLimit) { break; }
}
Console.WriteLine(inboundLogs.Count());
return inboundLogs.OrderByDescending(x => x.MessageDate);
};
}
As cosmosdb doesn't support Skip and Take you can also use offset and limit described here
or you can also use ContinuationToken of response to make sure there is still item, something like:
do
{
response = await setIterator.ReadNextAsync();
//List<dynamic> documents = response.Resource.ToList();
continuationToken = response.ContinuationToken;
inboundLogs.AddRange(response);
} while (continuationToken != null && inboundLogs.Count <= itemLimit);

Related

how to calculate sum of times in a column using foreach loop ASP.NET MVC

enter image description here
suppose A is my Table and inside this table i have one column like times
inside column name times i have n number of times
Example :-1st:-02:30
2nd:-03:25
3rd:-00:45
i want output like TotalTime=06:40
i got out put using jquery but i want how to do inside a controller using foreach loop please help me
my controller code:-
[HttpPost]
public ActionResult getTimeSheetByBasit(DateTime? CurrentDate, string ActivityTime)
//obj.UserDocumentList = ThidDb.UserDocument.Where(x => x.CreatedBy == UserId).ToList();
{
VM_TimeSheet ObjVM_TimeSheet = new VM_TimeSheet();
int LoggedUser = User.KEY();
string LoggedUserName = User.UserName();
string UserEmail = User.EmailID();
DateTime TimeIn, TimeOut;
string TimeInn, TimeOuut, TotalTime;
//code add here fot adding text box time with total houres enter by user select time Sheet
using (SecurenetDB SecurenetDB = new SecurenetDB())
{
ObjVM_TimeSheet.TimesheetList = SecurenetDB.AD_TimeSheet.Where(x => DbFunctions.TruncateTime(x.ActivityDate.Value) == DbFunctions.TruncateTime(CurrentDate) && x.UserKEY == LoggedUser).ToList();
TimeIn = SecurenetDB.AD_CardPunching.Where(x => DbFunctions.TruncateTime(x.EventDate) == DbFunctions.TruncateTime(CurrentDate) && x.UserName == LoggedUserName).Select(x => x.Time_In).FirstOrDefault();
TimeOut = SecurenetDB.AD_CardPunching.Where(x => DbFunctions.TruncateTime(x.EventDate) == DbFunctions.TruncateTime(CurrentDate) && x.UserName == LoggedUserName).Select(x => x.Time_Out).FirstOrDefault();
TimeInn = TimeIn.ToString("hh:mm tt");
TimeOuut = TimeOut.ToString("hh:mm tt");
TotalTime = SecurenetDB.AD_CardPunching.Where(x => DbFunctions.TruncateTime(x.EventDate) == DbFunctions.TruncateTime(CurrentDate) && x.UserName == LoggedUserName).Select(x => x.TotalHours).FirstOrDefault();
// ObjVM_TimeSheet.TimesheetList=SecurenetDB.AD_TimeSheet.Where(x=>x.Hours== TextTime && x.UserKEY == LoggedUser).ToList();
var sum = "00:00";
foreach(var iteam in ActivityTime)
{
sum = sum + iteam;
}
}
return Json(new
{
TimeSheetData = this.RenderPartialViewToString("TimeSheetData", ObjVM_TimeSheet.TimesheetList),
TimeIn = TimeInn,
TimeOut = TimeOuut,
TotalTime = TotalTime
}, JsonRequestBehavior.AllowGet);
}
enter image description here
Use TimeSpan
string[] times = new string[] {"02:30", "03:25", "00:45"};
TimeSpan totalTime = new TimeSpan(0);
foreach (string time in times)
{
TimeSpan ts = TimeSpan.Parse(time);
totalTime += ts;
}
Console.WriteLine(totalTime.ToString(#"hh\:mm"));
Output
06:40

How to check value with Enum Listing using C#

I am working on an application where I have implemented a functionality. The flow is like we are getting settings that can be 1 HOURS, 2 HOURS, 1 WEEK, 2 WEEKS or 1 MONTH. For Example, If I get Settings from Database like 1 HOUR then it will calculate the difference between two dates and check for 1 HOUR with the difference I am getting from the calculation. I have done it by using multiple IF checks but I want to optimize the code. Here is my implementation.
public enum TaskSchedulingEnum : int
{
[Description("1 HOUR")]
OneHour = 1,
[Description("2 HOURS")]
TwoHours = 2,
[Description("8 HOURS")]
EightHours = 8,
[Description("1 DAY")]
OneDay = 1,
[Description("3 DAYS")]
ThreeDays = 3,
[Description("1 WEEK")]
OneWeek = 1,
[Description("2 WEEKS")]
TwoWeeks = 2,
[Description("1 MONTH")]
OneMonth = 1,
[Description("ALWAYS")]
Always = 14
}
private async Task<bool> GetUserSettings(string companyId, DateTime? TaskStartDateTime)
{
// get company settings ...
var settings = await projulSettingsService.GetCompanyNotificationSettings(companyId, ProjulSettingsTypeEnum.Notifications);
var scheduleSettings = string.Empty;
if (settings.Where(x => x.Name == ProjulPortalSettings.GeneralSettingsNotificationIsDisabled).Select(x => x.Value).FirstOrDefault() == "false")
{
scheduleSettings = JsonConvert.DeserializeObject<string>(settings.Where(x => x.Name == ProjulPortalSettings.NotificationTaskAssignedImmediateWindow).Select(x => x.Value).FirstOrDefault());
if (!string.IsNullOrEmpty(scheduleSettings))
{
var _timespan = (DateTime.UtcNow - TaskStartDateTime).Value;
var difference = _timespan.TotalHours; // in hours..
TimeSpan days = TimeSpan.FromHours(difference); // days..
var weeks = (days.TotalDays % 365) / 7; // weeks
var months = (days.TotalDays % 365) / 30; // months
var list = ApplicationExtensions.GetEnumList<TaskSchedulingEnum>().ToList();
var _val = list.Where(x => x.Text == scheduleSettings).FirstOrDefault();
if (scheduleSettings == TaskSchedulingEnum.OneHour.GetEnumDescrip()
|| scheduleSettings == TaskSchedulingEnum.TwoHours.GetEnumDescrip()
|| scheduleSettings == TaskSchedulingEnum.EightHours.GetEnumDescrip())
{
if (difference == Convert.ToDouble(_val.Value))
return true;
}
else if (scheduleSettings == TaskSchedulingEnum.OneDay.GetEnumDescrip()
|| scheduleSettings == TaskSchedulingEnum.ThreeDays.GetEnumDescrip())
{
if (days.TotalDays == Convert.ToDouble(_val.Value))
return true;
}
else if (scheduleSettings == TaskSchedulingEnum.OneWeek.GetEnumDescrip()
|| scheduleSettings == TaskSchedulingEnum.TwoWeeks.GetEnumDescrip())
{
if (weeks == Convert.ToDouble(_val.Value))
return true;
}
else if (scheduleSettings == TaskSchedulingEnum.OneMonth.GetEnumDescrip())
{
if (months == Convert.ToDouble(_val.Value))
return true;
}
else if (scheduleSettings == TaskSchedulingEnum.Always.GetEnumDescrip())
{
return true;
}
return false;
}
}
return false;
}
Is there any way to write optimized and less code to achieve the functionality? I am getting the same settings from the database as mentioned in the Enum description. That can be a single value every time. Always check will return true always.
I would not recommend using enum values in this way. Let each enum value represent an arbitrary tag, that you separately convert to a duration with a extension method. For example:
public static TimeSpan ToDuration(this TaskSchedulingEnum self)
{
return self switch
{
TaskSchedulingEnum.OneHour => TimeSpan.FromHours(1),
TaskSchedulingEnum.TwoHours => TimeSpan.FromHours(2),
TaskSchedulingEnum.OneDay => TimeSpan.FromDays(1),
TaskSchedulingEnum.Always => Timeout.InfiniteTimeSpan,
};
}
Once you have a timespan to describe the duration it should be trivial to add this to any start time to get the end time or other similar operations.
Note that you might need special handling for the Always-value, since arithmetic operations with infinities will not work correctly. You might want to describe it with TimeSpan.MaxValue or use a TimeSpan? type instead, depending on how it is used.

Using Where predicate to filter detail.List with another list

I'm trying to get a set of Master-Detail records on the basis of a list of strings that I need to match with each detail's reference number column for each master. So, for example, I have this as a list of strings:
string[] listToFilterFor = new [] { "2729113", "2732623", "2734483", "2735355", "2752260" };
Anf the DAL function to filter:
public async Task<IQueryable<BILL_INFO>> GetBills(IDictionary<string, object> filterCriteria, string operationGuid)
{
var callerInfo = Shared.CommonAcross.Helper.GetCaller();
Logger.Info($"{LayerName} -> {callerInfo.MethodName} -> Started");
try
{
IList<BILL_INFO> intermResult;
using (var context = new FinanceConnection())
{
var result = context.BILL_INFOS
.Include(i => i.MASTER_ACCOUNT)
.Include(i => i.MASTER_PAY_MODE)
.Include(i => i.MASTER_BANK)
.Include(i => i.MASTER_CREDIT_CARD_TYPE)
.Include(i => i.MASTER_EDIRHAM_CARD_TYPE);
if (filterCriteria != null && filterCriteria.Any())
{
#region Keys
var billNumberKey = "BillNumber";
var cashierNumberKey = "AssignedCashiers";
var payModeIdKey = "PayModeId";
var depositIdKey = "DepositId";
var dateFromKey = "DateFrom";
var dateToKey = "DateTo";
var accountsKey = "Account";
var accountGroupsKey = "AccountGroups";
var referenceNumber = "ReferenceNumber";
var referenceNumbers = "ReferenceNumbers";
#endregion
if (filterCriteria.ContainsKey(billNumberKey) && filterCriteria.TryGetValue(billNumberKey, out var actualFilterBillNumber))
result = result.Where(where => where.BILL_NUMBER.Contains(actualFilterBillNumber.ToString()));
if (filterCriteria.ContainsKey(referenceNumbers) && filterCriteria.TryGetValue(referenceNumbers, out var actualReferenceNumbers))
{
result = result.Include(i => i.BILL_INFO_DETAIL);
result = result.Where(where => where.BILL_INFO_DETAIL.Any(p=>p.));
}
#region From/To Dates
DateTime? tempDateFrom = null;
DateTime? tempDateTo = null;
if (filterCriteria.ContainsKey(dateFromKey) && filterCriteria.TryGetValue(dateFromKey, out var actualDateFrom))
{
tempDateFrom = ((DateTime?)actualDateFrom)?.Date;
}
if (filterCriteria.ContainsKey(dateToKey) && filterCriteria.TryGetValue(dateToKey, out var actualDateTo))
{
tempDateTo = ((DateTime?)actualDateTo)?.Date.AddDays(1).AddMilliseconds(-1);
}
if (tempDateFrom.HasValue && tempDateTo.HasValue)
{
result = result.Where(where => where.BILL_DATE != null && where.BILL_DATE >= tempDateFrom && where.BILL_DATE <= tempDateTo);
}
else if (tempDateFrom.HasValue && !tempDateTo.HasValue)
{
result = result.Where(where => where.BILL_DATE != null && where.BILL_DATE >= tempDateFrom && where.BILL_DATE <= tempDateFrom);
}
else if (!tempDateFrom.HasValue && tempDateTo.HasValue)
{
result = result.Where(where => where.BILL_DATE != null && where.BILL_DATE >= tempDateTo.Value.Date && where.BILL_DATE <= tempDateTo);
}
#endregion
}
intermResult = await result.OrderByDescending(o => o.BILL_DATE).Take(10000).ToListAsync();
}
Logger.Info($"{LayerName} -> {callerInfo.MethodName} -> Returning");
return intermResult.AsQueryable();
}
catch (Exception exp)
{
Logger.Error($"{LayerName} -> {callerInfo.MethodName} -> Exception [{exp.Message}]", exp);
throw;
}
}
Task:
I need to go through the master records (BILL_INFOS) and look into each master's detail records (BILL_INFO_DETAILS) and try to match AnyOf listToFilterFor against BILL_INFO_DETAIL.REFERENCE_NUMBER
If i understand this correct, i apologize if i have not. Could you use an includes statement.
BILL_INFO.where(x => listToFilterFor.Includes(x.BILL_INFO_DETAILS.REFERENCE_NUMBER)
I finally sorted this one out as here were composite primary keys involved and a proper tuple was not possible. I found the solution through this question: Cannot create a relation between two tables with three primary keys
I was able to extract a subset.

Serializing Data Without Placeholder Key Names in C#

I am trying to modify the default WebAPI controller in VS2013 to return data in a way that can be consumed by HighCharts (in this case a Javascript timestamp and a value), and I've gotten pretty close with this code:
// GET: api/Readings
public HttpResponseMessage GetReadings(DateTime? starttime = null, DateTime? endtime = null, string name = "", string deviceId = "", bool latest = false, bool highcharts = false)
{
if (starttime == null)
{
starttime = DateTime.UtcNow.AddHours(-1);
}
if (endtime == null)
{
endtime = DateTime.UtcNow;
}
var readings = from r in db.Readings
join d in db.Devices on r.DeviceID equals d.Id
where (r.Timestamp >= starttime && r.Timestamp <= endtime)
select r;
if (name != "")
{
readings = readings.Where(p => p.Name == name);
}
if (deviceId != "")
{
readings = readings.Where(p => p.DeviceID == deviceId);
}
if (latest)
{
readings = readings.OrderByDescending(r => r.Timestamp).Take(1);
}
else
{
readings = readings.OrderBy(r => r.Timestamp);
}
if (highcharts)
{
var values = new List<Tuple<long, double>> { };
var data = readings.ToArray();
foreach (var item in data)
{
values.Add(new Tuple<long, double>(item.Timestamp.ToJavascriptTimestamp(), item.Value) );
}
return ControllerContext.Request.CreateResponse(HttpStatusCode.OK, values);
}
return ControllerContext.Request.CreateResponse(HttpStatusCode.OK, readings);
}
The challenge I am facing is that the output produced, which I want to look like this (sample from http://www.highcharts.com/studies/live-server-data.php, used in http://www.highcharts.com/studies/live-server.htm and from the tutorial http://www.highcharts.com/docs/working-with-data/live-data):
[1433364572000, 3]
Instead looks like this:
[{"m_Item1":1433364610337,"m_Item2":65.5}]
It appears that when the list of tuples gets serialized, it adds the generic m_Item1 and m_item2 keys.
I need to know what to do with my data in the if (highcharts) block to get it to output in the required highcharts friendly format.

LINQ get objects by date interval

I'm looking for a LINQ query that will select only those objects whose date interval is not higher than 20 seconds. For example:
AuthenticationEssay[] essays = new AuthenticationEssay[] {
new AuthenticationEssay() { Date = DateTime.Now.AddSeconds(20), Success = false },
new AuthenticationEssay() { Date = DateTime.Now.AddSeconds(24), Success = false },
new AuthenticationEssay() { Date = DateTime.Now.AddSeconds(29), Success = false },
new AuthenticationEssay() { Date = DateTime.Now.AddSeconds(38), Success = false },
new AuthenticationEssay() { Date = DateTime.Now.AddSeconds(125), Success = false },
new AuthenticationEssay() { Date = DateTime.Now.AddSeconds(347), Success = false },
new AuthenticationEssay() { Date = DateTime.Now.AddSeconds(400), Success = false },
new AuthenticationEssay() { Date = DateTime.Now.AddSeconds(422), Success = false },
new AuthenticationEssay() { Date = DateTime.Now.AddSeconds(446), Success = false },
new AuthenticationEssay() { Date = DateTime.Now.AddSeconds(467), Success = false }
};
I want to select only the first occurence of those objects whose date interval is not longer than 20 seconds against the next object. In this case, the query should return only the first 4 objects. Any idea? :(
UPDATE
Sorry, I forgot to mention that I'm sorting the array by descending order. So yes, the position in the array shouldn't have any effect on the query.
What about this?
var query from i in Enumerable.Range(1, count - 1)
let current = list[i]
let previous = list[i - 1]
// I see some empty positions in your example, nullability check
where current != null && previous != null
where (current.Date - previous.Date).TotalSeconds < 20
select previous;
EDIT: Obviously you have to call First() in order to get only the first element of the sequence.
query.First();
EDIT 2: I have just read you are ordering your results descending. In this case the query will be slightly different:
var query from i in Enumerable.Range(1, count - 1)
let current = list[i]
let previous = list[i - 1]
// I see some empty positions in your example, nullability check
where current != null && previous != null
where (previous.Date - current.Date).TotalSeconds < 20
select current;
It ain't pretty, but here you go...
var result = Enumerable.Range(0, essays.Count() - 1)
.Select(i => new {Essays1 = essays[i], Essays2 = essays[i + 1]})
.Where(a => a.Essays2 != null)
.Where(a => a.Essays2.Date - a.Essays1.Date < new TimeSpan(0, 0, 0, 20))
.Select(a => a.Essays1);
Does it have to be LINQ? I love LINQ, but I think something like this would be more readable...
var result = new List<AuthenticationEssay>();
for (var i = 0; i < (essays.Count() - 1); i++)
{
if (essays[i + 1] != null)
if (essays[i + 1].Date - essays[i].Date < new TimeSpan(0, 0, 0, 20))
result.Add(essays[i]);
}
It is probably possible to do it using built-in Linq operators, but in this case I think writing a specific method is easier. You could do something like that:
static IEnumerable<AuthenticationEssay> Filter(IEnumerable<AuthenticationEssay> list)
{
AuthenticationEssay last = null;
AuthenticationEssay previous = null;
foreach(var item in list)
{
if (last == null)
{
// Always return the first item
yield return item;
}
else if ((item.Date - last.Date).TotalSeconds >= 20)
{
yield return item;
}
previous = last;
last = item;
}
if (previous != null && last != null && (last.Date - previous.Date).TotalSeconds <= 20)
yield return last;
}
Of course it would be possible to make it more reusable, by making the method generic and passing a predicate as a parameter, but since it's a very specific requirement, I'm not sure it would be very useful...

Categories

Resources