VALIDATIONS WITH FLUENT VALIDATION - fluentvalidation

I need to do a specific validation with Fluent Validation, but I have read his documentation a few times and I did not find a solution for that. My validation class currently looks like this:
using FluentValidation;
using System;
namespace SaleTheaterTickets.Models.ViewModelValidators
{
public class GeneratedTicketViewModelValidator : AbstractValidator<GeneratedTicketViewModel>
{
public GeneratedTicketViewModelValidator()
{
RuleFor(x => x.CustomerName)
.NotEmpty().WithMessage("Digite o nome do cliente");
// .Matches("/ ^[a-zA-Z çÇÁáÉéÍíÓóÚúÃã']+$/i").WithMessage("Nome aceita apenas de A-Z");
RuleFor(x => x.BirthDate)
.NotEmpty().WithMessage("Digite a data de nascimento")
.Must(ValidDate).WithMessage("Data de nascimento tem que ser menor que hoje");
//.DependentRules(() => {
// RuleFor(x => x.NeedyChild)
// .Must(ValidQuestion).WithMessage("Resposta inválida: Você não é criança");
//});
RuleFor(x => x.FormOfPayment)
.NotEmpty().WithMessage("Selecione a forma de pagamento");
RuleFor(x => x.Seat)
.NotEmpty().WithMessage("Escolha a poltrona")
.NotNull().WithMessage("Poltrona inválida");
RuleFor(x => x.NeedyChild)
.NotEmpty().WithMessage("Responda a pergunta");
}
private static bool ValidDate(DateTime date)
{
if(date < DateTime.Now.Date)
{
return true;
}
return false;
}
//private static bool DiscountChild(DateTime date)
//{
// int age = DateTime.Now.Year - date.Year;
// if (age >= 2 && age <= 12)
// {
// return true;
// }
// return false;
//}
//private static bool ValidTotalChild(decimal Total)
//{
//}
//private static bool ValidQuestion( resposta)
//{
// int idade = DateTime.Now.Year - date.Year;
// bool _resposta = Convert.ToBoolean(resposta);
// if(_resposta == true)
// {
// if(idade >= 2 && idade <=12)
// {
// return true;
// }
// }
// return false;
//}
}
}
This system is for the sale of theater tickets, so I need the total to receive a 50% discount on the ticket value when the age of the people who are buying the ticket is between 2 and 12 years old and equal to or over 60 years old. In other words, children have a discount and the elderly too. However in my system I keep the birthday and not the age itself. I tried to use the must but the must returns bool (true or false) not allowing me to assign a value if the age is equal to both. can anybody help me?

Related

Best practice to check duplicate string data before insert data using Entity Framework Core in C#

I need an advice for my code. What I want to do is insert a row into a table using Entity Framework Core in ASP.NET Core.
Before inserting new data, I want to check if email and phone number is already used or not.
I want to return specifically, example if return = x, email used. If return = y, phone used.
Here's my code
public int Insert(Employee employee)
{
var checkEmail = context.Employees.Single(e => e.Email == employee.Email);
if (checkEmail != null)
{
var checkPhone = context.Employees.Single(e => e.Phone == employee.Phone);
if (checkPhone != null)
{
context.Employees.Add(employee);
context.SaveChanges();
return 1;
}
return 2;
}
return 3;
}
I'm not sure with my code, is there any advice for the best practice in my case?
I just don't like these "magic numbers" that indicate the result of your checks.... how are you or how is anyone else going to know what 1 or 2 means, 6 months down the road from now??
I would suggest to either at least create a constants class that make it's more obvious what these numbers mean:
public class CheckConstants
{
public const int Successful = 1;
public const int PhoneExists = 2;
public const int EmailExists = 3;
}
and then use these constants in your code:
public int Insert(Employee employee)
{
var checkEmail = context.Employees.Single(e => e.Email == employee.Email);
if (checkEmail != null)
{
var checkPhone = context.Employees.Single(e => e.Phone == employee.Phone);
if (checkPhone != null)
{
context.Employees.Add(employee);
context.SaveChanges();
return CheckConstants.Successful;
}
return CheckConstants.PhoneExists;
}
return CheckConstants.EmailExists;
}
and also in any code that calls this method and need to know about the return status code.
Alternatively, you could also change this to an enum (instead of an int):
public enum CheckConstants
{
Successful, PhoneExists, EmailExists
}
and then just return this enum - instead of an int - from your method:
public CheckConstants Insert(Employee employee)
{
var checkEmail = context.Employees.Single(e => e.Email == employee.Email);
if (checkEmail != null)
{
var checkPhone = context.Employees.Single(e => e.Phone == employee.Phone);
if (checkPhone != null)
{
context.Employees.Add(employee);
context.SaveChanges();
return CheckConstants.Successful;
}
return CheckConstants.PhoneExists;
}
return CheckConstants.EmailExists;
}
merge two database check to one Query
use SingleOrDefault instance of Single
public int Insert(Employee employee)
{
var checkEmail = context.Employees.Select (e=>new {e.Email , e.Phone }).SingleOrDefault(e => e.Email == employee.Email || e.Phone == employee.Phone);
if (checkEmail == null)
{
context.Employees.Add(employee);
context.SaveChanges();
return 1;
}
else if (checkEmail.Email == employee.Email)
return 3;
else
return 2;
}

Flyweight pattern in this simple net core Api uses more memory ram

I'm trying to aplicate Flyweight method pattern in a simple .net core Api to see how much memory is saved compared to not using the pattern.
I have two methods, the first one creates 5000 objects without uses the pattern and the another creates 5000 object using the pattern. After each of them create the objects, then they call a method that returns the current memory used by the App.
public class MemoryService : IMemoryService
{
private readonly TreeFactory _treeFactory;
public MemoryService()
{
_treeFactory = new TreeFactory();
}
//create without pattern
public long SetObjectsMemory()
{
List<Tree> trees = new List<Tree>();
for (int i = 0; i < 5000; i++)
{
var tree = new Tree()
{
Id = new Random().Next(1, 9999999),
Part = new PartTree()
{
Name = "Nameany",
Bark = "Barkany",
Color = "Colorany"
}
};
trees.Add(tree);
};
return Utilities.GetCurrentMemoryUsed();
}
//crete with flyweight pattern
public long SetObjectsMemoryFactory()
{
List<Tree> trees = new List<Tree>();
for (int i = 0; i < 5000; i++)
{
var tree = new Tree()
{
Id = new Random().Next(1, 9999999),
Part = _treeFactory.GetPartTree("Nameany", "Barkany", "Colorany")
};
trees.Add(tree);
}
return Utilities.GetCurrentMemoryUsed();
}
}
I use the pattern like a class that uses a list of Parts and return a part object if exists.
public class TreeFactory
{
private static List<PartTree> _parts;
public TreeFactory() {
_parts = new List<PartTree>();
}
public PartTree GetPartTree(string name, string bark, string color)
{
if (_parts.Any(x => x.Name == name && x.Bark == bark && x.Color == color))
{
return _parts.Where(x => x.Name == name && x.Bark == bark && x.Color == color).FirstOrDefault();
}
else {
var newpart = new PartTree()
{
Name = name,
Bark = bark,
Color = color
};
_parts.Add(newpart);
return newpart;
}
}
}
The way to get the current memory used by the App is using Process of this way (in Utilities class):
public static long GetCurrentMemoryUsed() {
Int64 memory;
using (Process proc = Process.GetCurrentProcess())
{
memory = proc.PrivateMemorySize64 / (1024 * 1024);
}
return memory;
}
And in my Startup i inject the MemoryService like a Singleton. In the controller i use 3 methods for call the functions:
[HttpGet, Route(nameof(WeatherForecastController.GenerateMemory))]
public IActionResult GenerateMemory()
{
var total=_memoryService.SetObjectsMemory();
return Ok(total);
}
[HttpGet, Route(nameof(WeatherForecastController.GenerateLiftMemory))]
public IActionResult GenerateLiftMemory()
{
var total = _memoryService.SetObjectsMemoryFactory();
return Ok(total);
}
[HttpGet, Route(nameof(WeatherForecastController.GetMemory))]
public IActionResult GetMemory()
{
var total = Utilities.GetCurrentMemoryUsed();
return Ok(total);
}
The problem is: When i call in the navigator the method in controller without pattern (/weatherforecast/GenerateMemory), then this returns (current)+2mb, but when i call the method
with pattern (/weatherforecast/GenerateLiftMemory) this returns (current)+3mb.
Why the method with pattern flyweight returns more used MB (growing) than the methods without the pattern ??
The repository with the code for test it. Gitlab repository memory api
The code which uses TreeFactory consumes more memory because its GetPartTree method called many times in a loop so as Linq methods Any and Where inside it. Both of these methods create additional Iterator objects under the hood in order to iterate through the collection and it causes additional memory consumption.
I wrote simple benchmark using BenchmarkDotNet with more options to demonstrate the issue
Extended MemoryService
public class MemoryService : IMemoryService
{
private const int TreeCount = 50000;
private readonly TreeFactory _treeFactory;
public MemoryService()
{
_treeFactory = new TreeFactory();
}
//crea objetos en memoria sin patrones
public decimal SetObjectsMemory()
{
List<Tree> trees = new List<Tree>();
for (int i = 0; i < TreeCount; i++)
{
var tree = new Tree()
{
Id = 1,
Part = new PartTree()
{
Name = "Nameany",
Bark = "Barkany",
Color = "Colorany"
}
};
trees.Add(tree);
};
return Utilities.GetCurrentMemoryUsed();
}
//crea objetos en memoria usando patron flyweight
public decimal SetObjectsMemoryFactory()
{
List<Tree> trees = new List<Tree>();
for (int i = 0; i < TreeCount; i++)
{
var tree = new Tree()
{
Id = 1,
Part = _treeFactory.GetPartTree("Nameany", "Barkany", "Colorany")
};
trees.Add(tree);
}
return Utilities.GetCurrentMemoryUsed();
}
public decimal SetObjectsMemoryFactoryImproved()
{
List<Tree> trees = new List<Tree>();
for (int i = 0; i < TreeCount; i++)
{
var tree = new Tree()
{
Id = 1,
Part = _treeFactory.GetPartTreeImproved("Nameany", "Barkany", "Colorany")
};
trees.Add(tree);
}
return Utilities.GetCurrentMemoryUsed();
}
//crea objetos en memoria usando patron flyweight
public decimal SetObjectsMemoryFactoryWithoutLambda()
{
List<Tree> trees = new List<Tree>();
for (int i = 0; i < TreeCount; i++)
{
var tree = new Tree()
{
Id = 1,
Part = _treeFactory.GetPartTreeWithoutLambda("Nameany", "Barkany", "Colorany")
};
trees.Add(tree);
}
return Utilities.GetCurrentMemoryUsed();
}
}
Extended TreeFactory
public class TreeFactory
{
private static List<PartTree> _parts;
public TreeFactory()
{
_parts = new List<PartTree>();
}
public PartTree GetPartTree(string name, string bark, string color)
{
if (_parts.Any(x => x.Name == name && x.Bark == bark && x.Color == color))
{
return _parts.Where(x => x.Name == name && x.Bark == bark && x.Color == color).FirstOrDefault();
}
var newpart = new PartTree()
{
Name = name,
Bark = bark,
Color = color
};
_parts.Add(newpart);
return newpart;
}
public PartTree GetPartTreeImproved(string name, string bark, string color)
{
var existingPart = _parts.Where(x => x.Name == name && x.Bark == bark && x.Color == color).FirstOrDefault();
if (existingPart != null)
return existingPart;
var newpart = new PartTree()
{
Name = name,
Bark = bark,
Color = color
};
_parts.Add(newpart);
return newpart;
}
public PartTree GetPartTreeWithoutLambda(string name, string bark, string color)
{
for (int i = 0; i < _parts.Count; i++)
{
var x = _parts[i];
if (x.Name == name && x.Bark == bark && x.Color == color)
return x;
}
var newpart = new PartTree()
{
Name = name,
Bark = bark,
Color = color
};
_parts.Add(newpart);
return newpart;
}
}
Benchmark in a separate console project
class Program
{
static void Main(string[] args)
{
var result = BenchmarkRunner.Run<MemoryBenchmark>();
}
}
[MemoryDiagnoser]
public class MemoryBenchmark
{
private IMemoryService memoryService;
[GlobalSetup]
public void Setup()
{
memoryService = new MemoryService();
}
[Benchmark]
public object SimpleTrees()
{
var trees = memoryService.SetObjectsMemory();
return trees;
}
[Benchmark]
public object FlyTrees()
{
var trees = memoryService.SetObjectsMemoryFactory();
return trees;
}
[Benchmark]
public object FlyTreesImproved()
{
var trees = memoryService.SetObjectsMemoryFactoryImproved();
return trees;
}
[Benchmark]
public object FlyTreesWithoutLambda()
{
var trees = memoryService.SetObjectsMemoryFactoryWithoutLambda();
return trees;
}
}
And its results
Method
Mean
Error
StdDev
Gen 0
Gen 1
Gen 2
Allocated
SimpleTrees
9.040 ms
0.1804 ms
0.2346 ms
718.7500
453.1250
265.6250
4.44 MB
FlyTrees
19.701 ms
0.1716 ms
0.1521 ms
2500.0000
906.2500
437.5000
15.88 MB
FlyTreesImproved
18.075 ms
0.2869 ms
0.2684 ms
1781.2500
625.0000
312.5000
10.92 MB
FlyTreesWithoutLambda
4.919 ms
0.0273 ms
0.0242 ms
421.8750
281.2500
281.2500
2.53 MB

How to find if items in 2 list match (but can't use direct equality)

I have this code here, to see if the items in both lists are identical:
for (final car in this.cars) {
bool found = false;
for (final car2 in garage2.cars) {
if (car2.id == car.id) {
found = true;
break;
}
}
if (!found) {
return false;
}
}
return true;
}
(I previously check if the 2 list lengths are equal). Is there a way to rewrite that so that I don't have O(n2) complexity?
As an option you can override quals and hashcode methods for class Car
something like this
class Car {
int id;
// other fields
#override
bool operator ==(Object o) => o is Car && id == o.id;
#override
int get hashCode => id.hashCode;
}
and then you can use the native method listEquals, which compares for deep equality.
import 'package:flutter/foundation.dart';
bool isEqual = listEquals<Car>(cars, garage2.cars);

How to calculate return to depot time and make it hard constraint

I am using the TimeWindowed version of the vehicle routing and I added to the vehicle an endOfShift time. I want to calculate the time of return to depot and make it hard constraint.
The returnToDepotTime is calculate in the ArrivalTimeUpdatingVariableListener, and I also changed the drl file I added
rule "returnToDepotBeforeEndOfShift"
when
Vehicle(endOfShift < returnToDepotTime, $endOfShift : endOfShift, $returnToDepotTime : returnToDepotTime)
then
scoreHolder.addHardConstraintMatch(kcontext, $endOfShift - $returnToDepotTime.intValue()); end
The problem is that OptaPlanner does not take returnToDepotTime into consideration and it is calculated but not taken by the hard constrains calculation. Any idea what to change?
Hi #Snukra thank you very much I solved it with a workaround I am saving everything in the last customer.
But I want to know where was my problem :)
So here is the important part of the vehicle object:
#PlanningEntity(difficultyComparatorClass = VehicleDifficultyComparator.class)
#XStreamAlias("Vehicle")
public class Vehicle extends AbstractPersistable implements Standstill {
Integer returnToDepotTime;
#CustomShadowVariable(variableListenerClass = ArrivalTimeUpdatingVariableListener.class, sources = { #CustomShadowVariable.Source(variableName = "returnToDepotTime") })
public Integer getReturnToDepotTime() {
return returnToDepotTime;
}
public void setReturnToDepotTime(Integer returnToDepotTime) {
this.returnToDepotTime = returnToDepotTime;
}
}
and this is the ArrivalTimeUpdatingVariableListener:
public class ArrivalTimeUpdatingVariableListener implements
VariableListener<Customer> {
public void beforeEntityAdded(ScoreDirector scoreDirector,
Customer customer) {
// Do nothing
}
public void afterEntityAdded(ScoreDirector scoreDirector,
Customer customer) {
updateVehicle(scoreDirector, customer);
}
public void beforeVariableChanged(ScoreDirector scoreDirector,
Customer customer) {
// Do nothing
}
public void afterVariableChanged(ScoreDirector scoreDirector,
Customer customer) {
updateVehicle(scoreDirector, customer);
}
public void beforeEntityRemoved(ScoreDirector scoreDirector,
Customer customer) {
// Do nothing
}
public void afterEntityRemoved(ScoreDirector scoreDirector,
Customer customer) {
// Do nothing
}
protected void updateVehicle(ScoreDirector scoreDirector,
Customer sourceCustomer) {
Standstill previousStandstill = sourceCustomer.getPreviousStandstill();
Integer departureTime = null;
Customer shadowCustomer = sourceCustomer;
Integer arrivalTime = 0;
Vehicle vehicle = null;
vehicle = sourceCustomer.getVehicle();
// here the start times are used
if (previousStandstill instanceof Customer) {
departureTime = ((Customer) previousStandstill).getDepartureTime();
arrivalTime = calculateArrivalTime(sourceCustomer, departureTime);
} else if (previousStandstill instanceof Vehicle) {
vehicle = (Vehicle) previousStandstill;
arrivalTime = calculateArrivalTimeFirstCustomer(sourceCustomer,
vehicle);
}
while (shadowCustomer != null
&& ObjectUtils.notEqual(shadowCustomer.getArrivalTime(),
arrivalTime)) {
scoreDirector.beforeVariableChanged(shadowCustomer, "arrivalTime");
shadowCustomer.setArrivalTime(arrivalTime);
scoreDirector.afterVariableChanged(shadowCustomer, "arrivalTime");
departureTime = shadowCustomer.getDepartureTime();
if (shadowCustomer.getNextCustomer() == null) {
scoreDirector.beforeVariableChanged(shadowCustomer,
"returnTimeToDepotIfLastOnTour");
//scoreDirector.beforeVariableChanged(vehicle,
// "returnToDepotTime");
int returnTimeToDepot = shadowCustomer.getArrivalTime()
+ shadowCustomer.getServiceDuration()
+ shadowCustomer.getTravelTimeTo(vehicle.getDepot());
vehicle.setReturnToDepotTime(returnTimeToDepot);
shadowCustomer
.setReturnTimeToDepotIfLastOnTour(returnTimeToDepot);
shadowCustomer.setEndOfShiftOfVehicle(vehicle.getEndOfShift());
scoreDirector.afterVariableChanged(shadowCustomer,
"returnTimeToDepotIfLastOnTour");
//scoreDirector.afterVariableChanged(vehicle,
// "returnToDepotTime");
}
shadowCustomer = shadowCustomer.getNextCustomer();
arrivalTime = calculateArrivalTime(shadowCustomer, departureTime);
}
}
private Integer calculateArrivalTimeFirstCustomer(Customer customer,
Vehicle vehicle) {
// calculate the earliest possible arrival time for this customer and
// this vehicle
int arrivalTime = vehicle.getStartOfShift()
+ customer.getLocation().getTravelTime(
vehicle.getStartLocation());
// if the time is before the redy time of a conatiner we take the ready
// time of a customer
if (customer.getReadyTime() > arrivalTime) {
arrivalTime = customer.getReadyTime();
}
return arrivalTime;
}
private Integer calculateArrivalTime(Customer customer,
Integer previousDepartureTime) {
if (customer == null) {
return null;
}
if (previousDepartureTime == null) {
// PreviousStandstill is the Vehicle, so we leave from the Depot
// at
// the best suitable time
int maxTime = Math.max(customer.getReadyTime(),
customer.getTravelTimeToPreviousStandstill());
return maxTime;
}
int arrivalTime = previousDepartureTime
+ customer.getTravelTimeToPreviousStandstill();
return arrivalTime;
}
}
The commented scoreDirector.beforeVariableChanged(vehicle, "returnToDepotTime"); and scoreDirector.afterVariableChanged(vehicle, "returnToDepotTime"); return the error.
Do you any have idea why?
Adjust the ArrivalTimeUpdatingVariableListener to also adjust the Vehicle's returnHomeTime for the Customer where getNextCustomer() is null.
If the scoreDirector is properly notified (before/afterVarChanged methods) that the Vehicle's returnHomeTime changed, the rules will update accordingly.

Class is CLS Compliant to .NET but not in Mono

I had to build my own Version class. In .NET it's CLS Compliant but in Mono its not for some reason. Any ideas why?
[Serializable]
public class Version : ICloneable, IComparable, IComparable<Version>, IEquatable<Version>
{
private int major;
private int minor;
private int revision;
private int build;
protected Version()
{
}
public Version(int major, int minor)
{
Major = major;
Minor = minor;
}
public Version(int major, int minor, int revision, int build) : this(major, minor)
{
Revision = revision;
Build = build;
}
public Version(string version)
{
if (string.IsNullOrWhiteSpace(version))
{
throw new ControlInfluence.Exceptions.ArgumentNullStringException("version");
}
string[] parts = version.Split('.');
if ((parts.Length != 4) && (parts.Length != 2))
{
throw new ArgumentException("'version' must have 2 or 4 numbers separated by '.'.", "version");
}
if (!int.TryParse(parts[0], out major))
{
throw new ArgumentException("'version' must have 2 or 4 numbers separated by '.'.", "version");
}
if (!int.TryParse(parts[1], out minor))
{
throw new ArgumentException("'version' must have 2 or 4 numbers separated by '.'.", "version");
}
if (!int.TryParse(parts[2], out revision))
{
throw new ArgumentException("'version' must have 2 or 4 numbers separated by '.'.", "version");
}
if (!int.TryParse(parts[3], out build))
{
throw new ArgumentException("'version' must have 2 or 4 numbers separated by '.'.", "version");
}
}
public int Major
{
get
{
return major;
}
set
{
major = value;
}
}
public int Minor
{
get
{
return minor;
}
set
{
minor = value;
}
}
public int Build
{
get
{
return build;
}
set
{
build = value;
}
}
public int Revision
{
get
{
return revision;
}
set
{
revision = value;
}
}
public override string ToString()
{
return string.Format(CultureInfo.InvariantCulture, "{0}.{1}.{2}.{3}", Major, Minor, Revision, Build);
}
public static bool operator <(Version left, Version right)
{
if ((left == null) || (right == null))
{
return false;
}
return left.CompareTo(right) < 0;
}
public static bool operator >(Version left, Version right)
{
if ((left == null) || (right == null))
{
return false;
}
return left.CompareTo(right) > 0;
}
#region ICloneable Members
public object Clone()
{
return new Version(Major, Minor, Revision, Build);
}
#endregion
#region IComparable Members
public int CompareTo(object obj)
{
Version other = obj as Version;
if (other == null)
{
return -1;
}
return CompareTo(other);
}
#endregion
#region IComparable<Version> Members
public int CompareTo(Version other)
{
if (other == null)
{
return -1;
}
int compareMajor = Major.CompareTo(other.Major);
if (compareMajor != 0)
{
return compareMajor;
}
int compareMinor = Minor.CompareTo(other.Minor);
if (compareMinor != 0)
{
return compareMinor;
}
int compareRevision = Revision.CompareTo(other.Revision);
if (compareRevision != 0)
{
return compareRevision;
}
return Build.CompareTo(other.Build);
}
#endregion
#region IEquatable<Version> Members
public bool Equals(Version other)
{
return CompareTo(other) == 0;
}
#endregion
public override bool Equals(object obj)
{
Version version = obj as Version;
if (version == null)
{
return false;
}
return Equals(version);
}
public static bool operator ==(Version left, Version right)
{
if (Object.ReferenceEquals(left, null) && Object.ReferenceEquals(right, null))
{
return true;
}
if (Object.ReferenceEquals(left, null) || Object.ReferenceEquals(right, null))
{
return false;
}
return left.Equals(right);
}
public static bool operator !=(Version left, Version right)
{
if ((left == null) || (right == null))
{
return false;
}
return !left.Equals(right);
}
}
The custom exception classes I throw are simply wrappers around ArgumentNullException that "auto fill" the message for me so they aren't adding any types to it really.
If it's CLS compliant in .NET but not on Mono, it is a bug in Mono. Please file a bug in http://bugzilla.xamarin.com