Generating a value dependent on another value with AutoPoco - c#

I'm using the great .NET library AutoPoco for creating test and Seed Data.
In my model I have 2 date properties, StartDate and EndDate.
I want the EndDate to be 3 hours after the start Date.
I've created a custom Data source for autopoco below that returns a random Datetime between a min and max date
class DefaultRandomDateSource : DatasourceBase<DateTime>
{
private DateTime _MaxDate { get; set; }
private DateTime _MinDate { get; set; }
private Random _random { get; set; }
public DefaultRandomDateSource(DateTime MaxDate, DateTime MinDate)
{
_MaxDate = MaxDate;
_MinDate = MinDate;
}
public override DateTime Next(IGenerationSession session)
{
var tspan = _MaxDate - _MinDate;
var rndSpan = new TimeSpan(0, _random.Next(0, (int) tspan.TotalMinutes), 0);
return _MinDate + rndSpan;
}
}
But in AutoPoco's configuration how can i get my EndDate to be say, 3 hours after the autogenerated start Date?
Here's the autopoco config
IGenerationSessionFactory factory = AutoPocoContainer.Configure(x =>
{
x.Conventions(c => { c.UseDefaultConventions(); });
x.AddFromAssemblyContainingType<Meeting>();
x.Include<Meeting>()
.Setup((c => c.CreatedBy)).Use<FirstNameSource>()
.Setup(c => c.StartDate).Use<DefaultRandomDateSource>(DateTime.Parse("21/05/2011"), DateTime.Parse("21/05/2012"));
});

If I am correctly understanding the problem you need: to set EndDate from StartDate. I had to create a new DataSource and get current item which we are constructing and read value from it. I haven't thoroughly checked but it might fail if StartDate is set after EndDate (though I think the properties are set in the order they are setup, read source code for AutoPoco). Also I am using latest version from CodePlex as of today (20 Feb 2012).
public class MeetingsGenerator
{
public static IList<Meeting> CreateMeeting(int count)
{
var factory = AutoPocoContainer.Configure(x =>
{
x.Conventions(c => { c.UseDefaultConventions(); });
x.Include<Meeting>()
.Setup((c => c.CreatedBy)).Use<FirstNameSource>()
.Setup(c => c.StartDate).Use<DefaultRandomDateSource>
(DateTime.Parse("21/May/2012"),
DateTime.Parse("21/May/2011"))
.Setup(c => c.EndDate).Use<MeetingEndDateSource>(0, 8);
});
return factory.CreateSession().List<Meeting>(count).Get();
}
}
public class Meeting
{
public string CreatedBy { get; set; }
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
}
public class MeetingEndDateSource : DatasourceBase<DateTime>
{
private int mMin;
private int mMax;
private Random mRandom = new Random(1337);
public MeetingEndDateSource(int min, int max)
{
mMin = min;
mMax = max;
}
public override DateTime Next(IGenerationContext context)
{
var node = (TypeGenerationContextNode)((context.Node).Parent);
var item = node.Target) as Meeting;
if (item == null)
return DateTime.Now;
return item.StartDate.AddHours(mRandom.Next(mMin, mMax + 1));
}
}
class DefaultRandomDateSource : DatasourceBase<DateTime>
{
private DateTime _MaxDate { get; set; }
private DateTime _MinDate { get; set; }
private Random _random = new Random(1337);
public DefaultRandomDateSource(DateTime MaxDate, DateTime MinDate)
{
_MaxDate = MaxDate;
_MinDate = MinDate;
}
public override DateTime Next(IGenerationContext context)
{
var tspan = _MaxDate - _MinDate;
var rndSpan = new TimeSpan(0
, _random.Next(0, (int)tspan.TotalMinutes)
, 0);
return _MinDate + rndSpan;
}
}

Related

How to pass time value from page.cs to ViewModel

How to paas time value from page.cs to ViewModel.
timevalue is string like "14h:15m"
Here I'm trying...
Page.cs
_model.StartTime = int.Parse(timevalue);
ViewModel
public DateTime StartTime { get; set; } = DateTime.Today;
public DateTime EndTime { get; set; }
public int Duration { get; set; }
private TimeSpan[] _StartTimeValues { get; set; }
private int _StartTimeIndex = -1;
public int StartTime
{
get { return _StartTime; }
set
{
_StartTimeIndex = value;
if (value >= 0)
{
StartTime =StartTime.Date.Add(_StartTimeValues[value]);
EndTime = StartTime.AddMinutes(Duration);
}
OnPropertyChanged(nameof(StartTime));
}
}
At first, please change the _StartTimeIndex's type to SpanTime, because the TimeDate.Add need a parameter type of SpanTime. Such as:
string time = "12h45m";
char[] hourandminute = new char[] { 'h', 'm' };
string[] temp = time.Split(hourandminute);
int hour = int.Parse(temp[0]);
int minutes = int.Parse(temp[1]);
TimeSpan timeSpan = new TimeSpan(hour, minutes, 0);

C# - Error CS0029 Cannot implicitly convert type 'int' to 'Core.Models.Mandate'

I have this model in my ASP.NET Core Web API:
Models:
namespace Core.Models
{
public class Mandate : EntityBase
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int? PaymentFrequency { get; set; } //1=Monthly, 2=Quarterly, 3=Yearly
public int? PaymentCount { get; set; }
public decimal Amount { get; set; }
}
}
ViewModel:
public class MandateVM
{
public DateTime StartDate { get; set; }
public DateTime EndDate { get; set; }
public int? PaymentFrequency { get; set; } //1=Monthly, 2=Quarterly, 3=Yearly
public decimal Amount { get; set; }
}
I have written some helpers that gets TotalMonth, TotalQuarter and TotalYear from StartDate and EndDate as show below:
namespace Infrastructure.Helpers
{
public static class ConstantHelper
{
private static IConfiguration Configuration { get; set; }
public static int GetTotalMonth(DateTime startDate, DateTime endDate)
{
int totalMonth = 12 * (startDate.Year - endDate.Year) + startDate.Month - endDate.Month;
return Convert.ToInt32(Math.Abs(totalMonth));
}
public static int GetTotalQuarter(DateTime startDate, DateTime endDate)
{
int firstQuarter = getQuarter(startDate);
int secondQuarter = getQuarter(endDate);
return 1 + Math.Abs(firstQuarter - secondQuarter);
}
private static int getQuarter(DateTime date)
{
return (date.Year * 4) + ((date.Month - 1) / 3);
}
public static int GetTotalYear(DateTime startDate, DateTime endDate)
{
int years = endDate.Year - startDate.Year;
if (startDate.Month == endDate.Month &&// if the start month and the end month are the same
endDate.Day < startDate.Day)// BUT the end day is less than the start day
{
years--;
}
else if (endDate.Month < startDate.Month)// if the end month is less than the start month
{
years--;
}
return Math.Abs(years);
}
}
}
EntityMapper:
public Mandate FromMandateCreateDtoToMandate(MandateVM mandateCreateVM)
{
if (mandateCreateVM == null)
{
return null;
}
Mandate mandate = new Mandate()
{
StartDate = mandateCreateVM.StartDate,
EndDate = mandateCreateVM.EndDate,
DueDate = mandateCreateVM.DueDate,
PaymentFrequency = mandateCreateVM.PaymentFrequency, //1=Monthly, 2=Quarterly, 3=Yearly
Amount = mandateCreateVM.Amount,
};
int numberOfTimes;
switch (mandateCreateVM.PaymentFrequency)
{
case 1:
return numberOfTimes = ConstantHelper.GetTotalMonth(mandate.StartDate, mandate.EndDate);
break;
case 2:
return numberOfTimes = ConstantHelper.GetTotalQuarter(mandate.StartDate, mandate.EndDate);
break;
default:
return numberOfTimes = ConstantHelper.GetTotalYear(mandate.StartDate, mandate.EndDate);
break;
}
mandate.PaymentCount = numberOfTimes;
return mandate;
}
PaymentFrequency determines number of times (numberOfTimes) payment will be made.
1 = Monthly
2 = Quarterly
3 = Yearly
I expected it to return numberOfTimes as int, but I got this error:
Error CS0029 Cannot implicitly convert type 'int' to 'Core.Models.Mandate'
It highlights:
return numberOfTimes = ConstantHelper.GetTotalMonth(mandate.StartDate, mandate.EndDate);
return numberOfTimes = ConstantHelper.GetTotalQuarter(mandate.StartDate, mandate.EndDate);
return numberOfTimes = ConstantHelper.GetTotalYear(mandate.StartDate, mandate.EndDate);
How do I get this resolved?
Thanks
Just delete the return in every cases of your switch case in FromMandateCreateDtoToMandate().
Those return will try to exit the function and return numberOfTimes (int) instead of, I presume, as you wanted only exit the switch case

c# Razor Pages, EF Core, How do I generate and add Child Records through Code to a Parent Record that has yet to be added using

I'm using c# Razor Pages with EF Core 5. I am not using MVC at all. I am trying to auto generate child records (months of the year) for a parent record (Year with Start Date/End Date). My model has the relations set up in them:
namespace Seasons.Models
{
public class AccountYears //Parent Record
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public Guid AccountYearsID { get; set; }
[Display(Name = "Accounts Year Name"), Required]
public string AccountYearsName { get; set; }
[Display(Name = "Start Date"), Required, DataType(DataType.Date)]
public DateTime DateStart { get; set; }
[Display(Name = "End Date"), Required, DataType(DataType.Date)]
public DateTime DateEnd { get; set; }
//AccountYearsMonths
public List<AccountYearsMonths> AccountYearsMonths { get; set; }
}
}
namespace Seasons.Models // Child Records
{
public class AccountYearsMonths
{
// [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public Guid AccountYearsMonthsID { get; set; }
[Required]
public Guid AccountYearsID { get; set; }
[Display(Name = "Month Name"), Required]
public string AccountYearsMonthsName { get; set; }
[Display(Name = "Start Date"), Required, DataType(DataType.Date)]
public DateTime DateStart { get; set; }
[Display(Name = "End Date"), Required, DataType(DataType.Date)]
public DateTime DateEnd { get; set; }
//AccountsYears
public AccountYears AccountYears { get; set; }
}
And then my AccountYears Create Page - Note the page has only fields for the parent to fill in when I create, I am wanting to generate all the child records in the code and save the whole transaction in one go.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.RazorPages;
using Microsoft.AspNetCore.Mvc.Rendering;
using MyApplication.Data;
using Seasons.Models;
namespace Seasons.Areas.Setup.Pages.FinanceAccountYears
{
public class CreateModel : PageModel
{
private readonly MyApplication.Data.ApplicationDbContext _context;
public CreateModel(MyApplication.Data.ApplicationDbContext context)
{
_context = context;
// _context.Attach(AccountYearsMonths);
}
public IActionResult OnGet()
{
return Page();
}
[BindProperty]
public AccountYears AccountYears { get; set; }
public List<AccountYearsMonths> AccountYearsMonths { get; set; }
// public List<AccountYearsMonths> AccountYearsMonths { get; set; }
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details, see https://aka.ms/RazorPagesCRUD.
public async Task<IActionResult> OnPostAsync()
{
if (!ModelState.IsValid)
{
return Page();
}
//AccYearsMonths();
//var emptyAccountYears = new AccountYears();
//if (await TryUpdateModelAsync<AccountYears>(
// emptyAccountYears,
// "AccYears",
// ay => ay.AccountYearsID, ay => ay.AccountYearsName, ay => ay.DateStart, ay => ay.DateEnd, ay => ay.Status))
//{
// _context.AccountYears.Add(emptyAccountYears);
AccYearsMonths();
_context.AccountYears.Add(AccountYears);
await _context.SaveChangesAsync();
//Guid AddedID = AccountYears.AccountYearsID;
//AccYearsMonths(AddedID);
//_context.AccountYears.Update(AccountYears);
//await _context.SaveChangesAsync();
return RedirectToPage("./Index");
}
public void AccYearsMonths()
{
// AccountYearsMonths = new List<AccountYearsMonths>();
DateTime MasterStartDate = AccountYears.DateStart;
DateTime MasterEndDate = AccountYears.DateEnd;
// Get the StartDate, MonthEndDate, and YearEndDate into variables
DateTime Date1 = new DateTime(MasterStartDate.Year, MasterStartDate.Month, 01);
DateTime Date2 = new DateTime(Date1.Year, Date1.Month, DateTime.DaysInMonth(Date1.Year, Date1.Month));
string MonthName = new string(Date1.ToString("MMM"));
while (Date1 < MasterEndDate)
{
AccountYears.AccountYearsMonths.Add(new AccountYearsMonths
{
AccountYearsMonthsName = MonthName,
DateStart = Date1,
DateEnd = Date2,
Status = "OPEN"
});
//AccountYearsMonths d = new AccountYearsMonths
//{
// AccountYearsMonthsName = MonthName,
// DateStart = Date1,
// DateEnd = Date2,
// Status = "OPEN",
// AccountYearsID = YearID
//};
// _context.AccountYearsMonths.Add(d);
// AccountYearsMonths.Add(d);
if (Date1.Month > 11)
{
Date1 = new DateTime(Date1.Year + 1, 01, 01);
}
else
{
Date1 = new DateTime(Date1.Year, Date1.Month + 1, 01);
} // Endif
Date2 = new DateTime(Date1.Year, Date1.Month, DateTime.DaysInMonth(Date1.Year, Date1.Month));
MonthName = Date1.ToString("MMM");
} // End While
} //End AccYearMonths
}
}
I get the following error when I run this code: System.NullReferenceException: 'Object reference not set to an instance of an object.' Which occurs when it runs this line: AccountYears.AccountYearsMonths.Add(new AccountYearsMonths
As you can see by all the commented out code I have tried a few different ways.
Any help would be greatly appreciated.
You need initiallize the AccountYearsMonths object like below:
while (Date1 < MasterEndDate)
{
//change here...
AccountYears.AccountYearsMonths = new List<AccountYearsMonths>();
AccountYears.AccountYearsMonths.Add(new AccountYearsMonths
{
AccountYearsMonthsName = MonthName,
DateStart = Date1,
DateEnd = Date2,
Status = "OPEN"
});
//....
}
Result:

Moving some models to ViewModel

I have Logging model that related to db table
Here is code:
public partial class Logging
{
public string Imei { get; set; }
public DateTime CurDateTime { get; set; }
public Nullable<System.DateTime> GPSDateTime2 { get; set; }
public Nullable<decimal> Latitude2 { get; set; }
public Nullable<decimal> Longitude2 { get; set; }
public int Speed { get; set; }
public Nullable<int> Datatype { get; set; }
public int Id { get; set; }
}
I want to calculate difference and decided to create ViewModel
Here is code
public class HeatmapViewModel:Logging
{
public TimeSpan? FirstStartDifference
{
get
{
if (CurDateTime != null)
{
var midnight = new DateTime(CurDateTime.Year, CurDateTime.Month, CurDateTime.Day, 00, 00, 00);
var difference = CurDateTime - midnight;
return difference;
}
return null;
}
}
public TimeSpan? LastStartDifference
{
get
{
if (CurDateTime != null)
{
var midnight = new DateTime(CurDateTime.Year, CurDateTime.Month, CurDateTime.Day, 23, 59, 00);
var difference = midnight - CurDateTime;
return difference;
}
return null;
}
}
public int coeff = 2;
public int Difference;
}
And on back-end I have this method
List<HeatmapViewModel> items = new List<HeatmapViewModel>();
var firstitem = ctx.Loggings.Where(x => x.Datatype == 2).AsEnumerable().Select(
x => new HeatmapViewModel
{
Longitude2 = x.Longitude2,
Latitude2 = x.Latitude2,
Difference = (int)(x.FirstStartDifference?.TotalMinutes ?? -1) * x.coeff
}).FirstOrDefault();
var lastItem = ctx.Loggings.Where(x => x.Datatype == 2).AsEnumerable().Select(
x => new HeatmapViewModel
{
Longitude2 = x.Longitude2,
Latitude2 = x.Latitude2,
Difference = (int)(x.LastStartDifference?.TotalMinutes ?? -1) * x.coeff
}).LastOrDefault();
But on this row Difference = (int)(x.FirstStartDifference?.TotalMinutes ?? -1) * x.coeff, I have error
Severity Code Description Project File Line Suppression State
Error CS1061 'Logging' does not contain a definition for 'FirstStartDifference' and no extension method 'FirstStartDifference' accepting a first argument of type 'Logging' could be found (are you missing a using directive or an assembly reference?) Heatmap C:\Users\nemes\source\repos\Heatmap\Heatmap\Controllers\HomeController.cs 28 Active
How I can use property from VIewModel
Use multi-line lambda instead:
var firstitem = Loggings.Where(x => x.Datatype == 2).AsEnumerable().Select(
x =>
{
var vm = new HeatmapViewModel
{
Longitude2 = x.Longitude2,
Latitude2 = x.Latitude2
};
vm.Difference = (int)(vm.FirstStartDifference?.TotalMinutes ?? -1) * vm.coeff;
return vm;
}).FirstOrDefault();
Note: Please read comments below your post, because you are mixing types. Variable x is of type Logging

Enumerate Class Properties in C#

I have a class Similar to this
public class Model
{
public TimeSpan Time1 {get; set;}
public TimeSpan Time2 { get; set; }
public TimeSpan Time3 { get; set; }
public TimeSpan Time4 { get; set; }
}
Now Let's Imagine I have to populate the times during runtime and then Figure out the time remaining between Time 1 and Time 2, then when that passes Find the time remaining between Time2 and Time3 and so on. However, I need to take into account what the time is right now.
For Example:
Now it is 1:00 PM
Time1=5:00 AM
Time 2 = 12:00 PM
Time 3= 4:00 PM
Time 4 = 6:00 PM
So since the time is 1:00PM, I need to find the difference between Time 2 and Time 3
Now is there a smarter way other than reflection to determine this? Should i add something in my class
If you need to keep the existing structure of your class, you could add a method to enumerate through the times:
public class Model
{
public TimeSpan Time1 {get; set;}
public TimeSpan Time2 { get; set; }
public TimeSpan Time3 { get; set; }
public TimeSpan Time4 { get; set; }
public IEnumerable<TimeSpan> GetTimes()
{
yield return Time1;
yield return Time2;
yield return Time3;
yield return Time4;
}
}
And use it like this:
foreach (TimeSpan time in model.GetTimes())
{
// use the TimeSpan
}
Why would you not use an array or list?
public class Model
{
public List<DateTime> Dates { get; set; }
}
If I'm understanding your question correctly, why not have a Dictionary<TimeSpan, string> where the key is actual TimeSpan, and the value is the name, e.g. "Time1"? This way, you can sort the keys, find the pair that you need, and then get at their names.
You could add a property or method that would return the times as a list for easier processing. Then your external code could access the times as either a list or as individual properties. You still have to explicitly access each property, but at least it's from within the same class, so you're not coupling your external code to the data structure as tightly.
This is untested and needs some optimization, but just as a thought example, use an array and iterate through it.
public class Model
{
private TimeSpan[] _timeSpans = new TimeSpan[4] { new TimeSpan(), new TimeSpan(), new TimeSpan(), new TimeSpan() };
public TimeSpan Time1
{
get { return _timeSpans[0]; }
set { _timeSpans[0] = value; }
}
public TimeSpan Time2
{
get { return _timeSpans[1]; }
set { _timeSpans[1] = value; }
}
public TimeSpan Time3
{
get { return _timeSpans[2]; }
set { _timeSpans[2] = value; }
}
public TimeSpan Time4
{
get { return _timeSpans[3]; }
set { _timeSpans[3] = value; }
}
// DateTime.TimeOfDay holds the time portion of a time
public TimeSpan GetDifference(TimeSpan currentTime)
{
int start = -1;
for(int i = 0; i<_timeSpans.Length;i++)
{
if(_timeSpans[i] >= currentTime)
{
start = i;
break;
}
}
if(start == -1) throw new ArgumentException("handle the case where currentTime is smaller than all of them");
int end = (start + 1 < _timeSpans.Length) ? start + 1 : 0;
return _timeSpans[end] - _timeSpans[start];
}
Constructing an array provides for a simple linq statement to calculate the time span:
public class Model
{
public TimeSpan Time1 { get; set; }
public TimeSpan Time2 { get; set; }
public TimeSpan Time3 { get; set; }
public TimeSpan Time4 { get; set; }
public TimeSpan GetSpan(TimeSpan time)
{
var times = new[] { Time1, Time2, Time3, Time4 };
return Enumerable.Range(1, times.Length - 1)
.Select(i => new[] { times[i - 1], times[i] })
.Where(t => t[0] <= time && time < t[1])
.Select(t => t[1] - t[0])
.FirstOrDefault();
}
}

Categories