Im having a method like this
public List<GSMData> GetGSMList()
{
return meters.Select(x => x.Gsmdata.Last())
.ToList();
}
and i get a "Value cannot be null." exeption. How do i make it so the value can be null?
GSMData object
public class GSMData : Meter
{
public DateTime TimeStamp { get; set; }
public int SignalStrength { get; set; }
public int CellID { get; set; }
public int LocationAC { get; set; }
public int MobileCC { get; set; }
public int MobileNC { get; set; }
public string ModemManufacturer { get; set; }
public string ModemModel { get; set; }
public string ModemFirmware { get; set; }
public string IMEI { get; set; }
public string IMSI { get; set; }
public string ICCID { get; set; }
public string AccessPointName { get; set; }
public int MobileStatus { get; set; }
public int MobileSettings { get; set; }
public string OperatorName { get; set; }
public int GPRSReconnect { get; set; }
public string PAP_Username { get; set; }
public string PAP_Password { get; set; }
public int Uptime { get; set; }
}
you better check for Gsmdata having items or not
public List<GSMData> GetGSMList()
{
return meters.Where(x=>x.Gsmdata!=null && x.Gsmdata.Any()).Select(x => x.Gsmdata.Last())
.ToList();
}
I'm guessing your Gsmdata property is null.
In this case, you could use the Linq .Where() method, to make this:
public List<GSMData> GetGSMList()
{
return meters.Where(x => x.Gsmdata != null)
.Select(x => x.Gsmdata.Last())
.ToList();
}
But you should clarify what exactly is null for better answers.
Try excluding null items by filtering the list immediately, and before doing the select.
public List GetGSMList()
{
return meters.Where(x=> x.Gsmdata != null).Select(x => x.Gsmdata.Last())
.ToList();
}
Related
I am trying to map an entity with a model but it's giving an error how can I check which property is causing the error?
Error: AutoMapper.AutoMapperMappingException: 'Error mapping types.'
AutoMapperMappingException: Missing type map configuration or unsupported mapping.
This exception was originally thrown at this call stack:
AutoMapper.Mapper.MapCore<TSource, TDestination>(TSource, TDestination, AutoMapper.ResolutionContext, System.Type, System.Type, AutoMapper.MemberMap)
AutoMapper.Mapper.AutoMapper.IInternalRuntimeMapper.Map<TSource, TDestination>(TSource, TDestination, AutoMapper.ResolutionContext, System.Type, System.Type, AutoMapper.MemberMap)
AutoMapper.ResolutionContext.MapInternal<TSource, TDestination>(TSource, TDestination, AutoMapper.MemberMap)
public class AutoMapperProfile : Profile
{
public AutoMapperProfile()
{
CreateMap<Account, AccountModel>();
CreateMap<AccountModel, Account>();
CreateMap<ServicePlan, ServicePlanModel>()
.ForMember(ServicePlanModel => ServicePlanModel.ServicePlanDetails, opt => opt.MapFrom(src => src.ServicePlanDetails.ToList()))
.ForMember(dest => dest.Lines, opt => opt.MapFrom(src => src.NLines ?? default))
.ForMember(dest => dest.StartDate, opt => opt.MapFrom(src => src.DateStart))
.ForMember(dest => dest.EndDate, opt => opt.MapFrom(src => src.DateEnd))
.ForMember(dest => dest.MonthlyCharges, opt => opt.MapFrom(src => src.AmountMonthly))
.ForMember(dest => dest.OneTimeCharges, opt => opt.MapFrom(src => src.AmountOnetime));
}
}
public async Task<List<ServicePlanModel>> GetServicePlansWithDetails(long accountId)
{
var plan = mapper.Map<ServicePlan, ServicePlanModel>(servicePlan);
}
public partial class ServicePlan
{
public ServicePlan()
{
ServicePlanDetails = new HashSet<ServicePlanDetail>();
}
public long PlanId { get; set; }
public decimal PhoneId { get; set; }
public byte? NLines { get; set; }
public DateTime? DateStart { get; set; }
public DateTime? DateEnd { get; set; }
public decimal? AmountMonthly { get; set; }
public decimal? AmountOnetime { get; set; }
public string? ContractType { get; set; }
public string? CallerId { get; set; }
public bool? Active { get; set; }
public short? ResellerId { get; set; }
public int? OnetimeInvoiceNo { get; set; }
public bool? IsRequest { get; set; }
public string? RequestType { get; set; }
public string? NewValue { get; set; }
public DateTime? RequestDate { get; set; }
public string? RequestBy { get; set; }
public bool? IsRejected { get; set; }
public bool? IsApproved { get; set; }
public DateTime? ApprovedWhen { get; set; }
public string? ApprovedBy { get; set; }
public string? Comments { get; set; }
public string? AdditionalDetails { get; set; }
public string? VideoTronId { get; set; }
public string? Zone { get; set; }
public string? PrevProvider { get; set; }
public bool? Charge911Tax { get; set; }
public string? ContractTerms { get; set; }
public long? ContractId { get; set; }
public int AllowedBandwidth { get; set; }
public DateTime? ServiceStartDate { get; set; }
public string? AppointmentTime { get; set; }
public DateTime? AppointmentEmailSentOn { get; set; }
public string? TrackingNumber { get; set; }
public bool? HasNumberPort { get; set; }
public DateTime? EstPortDate { get; set; }
public DateTime? PortCompletedOn { get; set; }
public bool? IsExGbchargesLimited { get; set; }
public decimal? ExGbchagesLimitAmt { get; set; }
public bool? IsPreVisitSch { get; set; }
public DateTime? PreVisitSchDate { get; set; }
public string? PreVisitSchTime { get; set; }
public bool? MoniterBwUsage { get; set; }
public int? BwWarnLimit { get; set; }
public string? DslaccountId { get; set; }
public string? BellGisId { get; set; }
public string? DslPassword { get; set; }
public bool? IsPasswordPassed { get; set; }
public bool? IsDslUserPassed { get; set; }
public string? CogecoId { get; set; }
public int? ServiceProviderId { get; set; }
public string? RogersId { get; set; }
public decimal? InternetSpeed { get; set; }
public bool? ModemRental { get; set; }
public bool? RouterRental { get; set; }
public bool? Atarental { get; set; }
public string? DslaccountDomain { get; set; }
[NotMapped]
public virtual ICollection<ServicePlanDetail> ServicePlanDetails { get; set; }
}
public class ServicePlanModel
{
public ServicePlanModel()
{
ServicePlanDiscounts = new List<ServicePlanDiscount>();
ServicePlanDetails = new List<ServicePlanDetail>();
}
[Key]
public Int64 PlanId { get; set; }
public Int64? ContractId { get; set; }
public int ResellerId { get; set; }
public Int64 PhoneId { get; set; }
public bool IsPhone { get; set; }
public Int32? OneTimeInvoiceId { get; set; }
public UInt16 Lines { get; set; }
public DateTime StartDate { get; set; }
public DateTime? EndDate { get; set; }
public Decimal MonthlyCharges { get; set; }
public Decimal OneTimeCharges { get; set; }
public String ContractType { get; set; }
public String CallerId { get; set; }
public Boolean IsActive { get; set; }
public Boolean IsRequest { get; set; }
public Boolean IsRejected { get; set; }
public Boolean IsApproved { get; set; }
public Boolean Charge911Tax { get; set; }
public DateTime ApprovedOn { get; set; }
public String ApprovedBy { get; set; }
public String Comments { get; set; }
public String ContractTerms { get; set; }
public String AdditionalDetails { get; set; }
public String VideoTronId { get; set; }
public String Zone { get; set; }
public String PreviousProvider { get; set; }
public String RequestType { get; set; }
public String NewValue { get; set; }
public DateTime? RequestDate { get; set; }
public String RequestedBy { get; set; }
//public PhoneNumber PhoneNumber { get; set; }
public List<ServicePlanDetail> ServicePlanDetails { get; set; }
public List<ServicePlanDiscount> ServicePlanDiscounts { get; set; }
public bool IsLandLinePlan
{
get
{
if (ServicePlanDetails != null)
{
return ServicePlanDetails.Any(spd => new String[] { "landline-r", "landline-b", "plan_10103", "plan_10104", "plan_10105" }.Contains(spd.ServiceCode));
}
return false;
}
}
public String ServicePlanName
{
get
{
if (ServicePlanDetails != null && ServicePlanDetails.Count > 0)
{
var plan = ServicePlanDetails.SingleOrDefault(spd => spd.IsPlan);
if (plan != null)
{
if (IsPhone)
{
return String.Format("{0} ({3}) ({1} x {2})", plan.ServiceTitle, plan.UnitPrice.ToString("N2"), plan.Quantity, PhoneId.ToString("###-###-####"));
}
return String.Format("{0} ({1} x {2})", plan.ServiceTitle, plan.UnitPrice.ToString("N2"), plan.Quantity);
}
}
return String.Empty;
}
}
public String MonthlyChargesDetails
{
get
{
if (ServicePlanDetails != null && ServicePlanDetails.Count > 0)
{
var items = ServicePlanDetails.Where(spd => spd.IsPlan == false & spd.UnitPrice > 0 & spd.ServiceType.Equals(Constants.SERVICE_TYPE_MONTHLY)).ToList();
var details = new StringBuilder();
foreach (var spd in items)
{
details.Append(String.Format("{0} ({1} x {2}) ", spd.ServiceTitle, spd.UnitPrice.ToString("N2"),
spd.Quantity));
}
return details.ToString();
}
return String.Empty;
}
}
//public String OnetimeChargesDetails
//{
// get
// {
// if (ServicePlanDetails != null && ServicePlanDetails.Count > 0)
// {
// var items = ServicePlanDetails.Where(spd => spd.IsPlan == false & spd.UnitPrice > 0 & spd.ServiceType.Equals(Constants.SERVICE_TYPE_ONETIME)).ToList();
// var details = new StringBuilder();
// foreach (var spd in items)
// {
// details.Append(String.Format("{0} ({1} x {2}) ", spd.ServiceTitle, spd.UnitPrice.ToString("N2"),
// spd.Quantity));
// }
// return details.ToString();
// }
// return String.Empty;
// }
//}
public List<ServicePlanDetail> OnetimeChargesDetails
{
get
{
if (ServicePlanDetails != null && ServicePlanDetails.Count > 0)
{
return ServicePlanDetails.Where(spd => spd.IsPlan == false & spd.ServiceType.Equals(Constants.SERVICE_TYPE_ONETIME)).ToList();
}
return null;
}
}
public List<ServicePlanDetail> FreeServicesDetails
{
get { return ServicePlanDetails != null ? ServicePlanDetails.Where(s => s.UnitPrice == 0 && !s.ServiceType.Equals("month")).ToList() : null; }
}
public List<ServicePlanDetail> DiscountedServicesDetail
{
get
{
return ServicePlanDetails != null ?
ServicePlanDetails.Where(s => s.ResellerService != null && s.UnitPrice < s.ResellerService.SuggestedPrice && !s.ServiceType.Equals("month")).ToList() : null;
}
}
public string Modem_MAC { get; set; }
public string TrackingNumber { get; set; }
}
I tried debugging but could not find the error.
Take a look at the source for AutoMapperMappingException. There are a number of properties on the exception that can be examined while under a debugger.
From the source...
public TypePair? Types { get; set; }
public TypeMap TypeMap { get; set; }
public MemberMap MemberMap { get; set; }
These properties are used to create the string for the Message property.
If for some reason that doesn't give you enough information, a way more intensive and semi-destructive way (have a backup of your source) is to cut half of the properties from the source/target types and see if the error still occurs. If yes, cut in half again, if no take the other properties and try again.
Basically, you are doing a binary search to narrow down the problem until it becomes obvious.
I have table clientcontactcompany table and checking for if combination of email Address and clientcompanyId exist. I have set a unique constraint on both the fields. I am trying to write logic in my repository layer
Client company contact class
public partial class ClientCompanyContact
{
public ClientCompanyContact()
{
FxforwardTrade = new HashSet<FxforwardTrade>();
Fxoption = new HashSet<Fxoption>();
}
public int Id { get; set; }
public int ClientCompanyId { get; set; }
public string Title { get; set; }
public string Forename { get; set; }
public string Surname { get; set; }
public string Email { get; set; }
public string TelephoneDirect { get; set; }
public string TelephoneMobile { get; set; }
public string TelephoneOther { get; set; }
public DateTime? Birthday { get; set; }
public bool Authorized { get; set; }
public byte[] UpdateTimeStamp { get; set; }
public int UpdatedByAuthUserId { get; set; }
public DateTime UpdatedDateTime { get; set; }
public string Notes { get; set; }
public string Fullname { get; set; }
public bool RecNotifications { get; set; }
public bool RecAmreport { get; set; }
public int? AuthUserId { get; set; }
public string Position { get; set; }
public bool? PrimaryContact { get; set; }
public bool RecActivityReport { get; set; }
public bool IsDeleted { get; set; }
public string Aspnumber { get; set; }
public DateTime? AspcreationDate { get; set; }
public DateTime? LastTelephoneChangeDate { get; set; }
public DateTime? LastEmailChangeDate { get; set; }
public string BloombergGpi { get; set; }
public string NiNumber { get; set; }
public AuthUser AuthUser { get; set; }
public ClientCompany ClientCompany { get; set; }
public AuthUser UpdatedByAuthUser { get; set; }
public ICollection<FxforwardTrade> FxforwardTrade { get; set; }
public ICollection<Fxoption> Fxoption { get; set; }
}
Client contact repository
public IGenericRepo<ClientCompanyContact> ClientCompanyContactRepository =>
_clientCompanyContactRepository = _clientCompanyContactRepository ?? new GenericRepo<ClientCompanyContact>(Context);
This is what I tried snd not compiling . What’s the right of doing it
public async Task<bool> UniqueEmail(string email, string ClientCompanyId)
{
return await ClientCompanyContactRepository.Get().Where(x => x.Email == email && x.ClientCompanyId = ClientCompanyId);
}
Firstly, pass the ClientCompanyID in as an int, then you're missing an equal sign, should be:
x => x.Email == email && x.ClientCompanyId == ClientCompanyId
You have few small but deadly mistakes in your code.
The method should look more like this.
public async Task<bool> UniqueEmail(string email, int clientCompanyId)
{
var count = await ClientCompanyContactRepository.Get()
.Count(x => x.Email == email && x.ClientCompanyId == clientCompanyId);
return count < 2;
}
Please note that .Count(x => ...) could be .Where( x => ...).Count().
Changes:
Pass clientCompanyId as int, so 'int ClientCompanyId'
You need to return a bool not a list objects, so 'bool anyMatching = x.Any(...); return !anyMatching'.
Parameter names should start with common letter, so 'int clientCompanyId'
Comparison uses ==, not = so '== ClientCompanyId'
If Get is async it should be GetAsync, or even GetAllAsync.
Update: it seems that Get is not async. Let's drop all async parts.
public bool UniqueEmail(string email, int clientCompanyId)
{
var count = ClientCompanyContactRepository.Get()
.Count(x => x.Email == email && x.ClientCompanyId == clientCompanyId);
return count < 2;
}
Please note we don't know what Get() returns so we don't know if the filtering will happen in memory or in the database.
I suspect that Get() may return all records so the filtering will happen in memory. You may want to move UniqueEmail into the repository.*
I want to know which approach is faster. I have the following class:
public class AccountBalance
{
public long AccountID { get; set; }
public string AccountNumber { get; set; }
[NotRequiredForDataTable]
public IEnumerable<AccountMediaBalance> AccountMediaBalances { get; set; }
}
public class AccountMediaBalance
{
public long AccountID { get; set; }
public long MediaID { get; set; }
public string MediaSerialNumber { get; set; }
public decimal? CashAmount { get; set; }
public int FareID { get; set; }
public bool ShowID { get; set; }
public bool ShareCash { get; set; }
public bool ShareToken { get; set; }
public bool SharePass { get; set; }
public IEnumerable<Token> Tokens { get; set; }
public IEnumerable<Pass> Passes { get; set; }
}
public class Token
{
public long TokenID { get; set; }
public long AccountID { get; set; }
public long MediaProductID { get; set; }
public long MediaID { get; set; }
public long? ActivateByMediaID { get; set; }
public string SerialNumber { get; set; }
public decimal? TransferValue { get; set; }
public DateTimeOffset CreateTime { get; set; }
public DateTimeOffset? ActivateTime { get; set; }
public DateTimeOffset? ExpiryTime { get; set; }
}
public class Pass
{
public long MediaProductID { get; set; }
public long AccountID { get; set; }
public long MediaID { get; set; }
public int ProductID { get; set; }
public long? ActivateByMediaID { get; set; }
public string SerialNumber { get; set; }
public DateTimeOffset CreateTime { get; set; }
public DateTimeOffset? ActivateTime { get; set; }
public DateTimeOffset? ExpiryTime { get; set; }
}
I have a list of AccountBalance data as List<AccountBAlance> and I want to transform data in a way that I want to separate AccountMediaBalance collection in one list, All tokens in one list and all passes in a separate list.
There are two approaches for doing this:
public void SaveAccountBalances(List<AccountBalance> accountBalances)
{
if (accountBalances != null)
{
var mediaBalances = accountBalances.SelectMany(x => x.AccountMediaBalances ??
Enumerable.Empty<AccountMediaBalance>()).ToList();
var tokens = mediaBalances.SelectMany(x => x.Tokens ?? Enumerable.Empty<Token>()).ToList();
var passes = mediaBalances.SelectMany(x => x.Passes ?? Enumerable.Empty<Pass>()).ToList();
}
}
The other approach would be like following:
public void SaveAccountBalances(List<AccountBalance> accountBalances)
{
var mediaBalances = new List<AccountMediaBalance>();
var tokens = new List<Token>();
var passes = new List<Pass>();
if (accountBalances != null)
{
foreach (var item in accountBalances)
{
mediaBalances.AddRange(item.AccountMediaBalances ?? Enumerable.Empty<AccountMediaBalance>());
}
foreach (var item in mediaBalances)
{
tokens.AddRange(item.Tokens ?? Enumerable.Empty<Token>());
passes.AddRange(item.Passes ?? Enumerable.Empty<Pass>());
}
}
}
Performance is a big concern. Can anyone put me in the right direction and let me know which approach is faster and why?
foreach loop uses GetEnumerator directly, while linq creates the query object first and then GetEnumerator. So it is naturally a little bit faster to use foreach loop for a single iteration but it still makes the code look better to use linq.
Getting straight to the point, I've got the following Models:
public abstract class ControlData
{
public DateTime CreatedDate { get; set; }
public int CreatedById { get; set; }
[ForeignKey("CreatedById")]
public Collaborator CreatedBy { get; set; }
public DateTime? UpdatedDate { get; set; }
public int? UpdatedById { get; set; }
[ForeignKey("UpdatedById")]
public Collaborator UpdatedBy { get; set; }
}
[Table("My_Position_Table")]
public class Position : ControlData
{
[Key]
[Column("PositionId")]
public int Id { get; set; }
[Column("PositionStatusId")]
public int StatusId { get; set; }
[ForeignKey("StatusId")]
public PositionStatus Status { get; set; }
public int OpportunityId { get; set; }
[ForeignKey("OpportunityId")]
public Opportunity Opportunity { get; set; }
public int Total { get; set; }
[Column("PositionDurationId")]
public int DurationId { get; set; }
[ForeignKey("DurationId")]
public PositionDuration Duration { get; set; }
public DateTime StartDate { get; set; }
//TODO Agregar las otras propiedades con sus respectivos catalogos
public string PracticeId { get; set; }
[ForeignKey("PracticeId")]
public Practice Practice { get; set; }
public int RoleId { get; set; }
[ForeignKey("RoleId")]
public PersonRole Role { get; set; }
public int PlatformId { get; set; }
[ForeignKey("PlatformId")]
public Platform Platform { get; set; }
public int LevelId { get; set; }
[ForeignKey("LevelId")]
public Level Level { get; set; }
public int EnglishLevelId { get; set; }
[ForeignKey("EnglishLevelId")]
public EnglishLevel EnglishLevel { get; set; }
public string CountryId { get; set; }
public int LocationId { get; set; }
[ForeignKey("LocationId")]
public Location Location { get; set; }
public int? OfficeId { get; set; }
public int OperationId { get; set; }
[ForeignKey("OperationId")]
public Person Operation { get; set; }
public int? EvaluatorId { get; set; }
[ForeignKey("EvaluatorId")]
public Collaborator Evaluator { get; set; }
public int? SourcerId { get; set; }
[ForeignKey("SourcerId")]
public Collaborator Sourcer { get; set; }
public List<Candidate> Candidates { get; set; }
public int? PositionCancellationReasonId { get; set; }
[ForeignKey("PositionCancellationReasonId")]
public PositionCancellationReason CancellationReason { get; set; }
public string CancellationComments { get; set; }
public int? CancellationById { get; set; }
[ForeignKey("CancellationById")]
public Collaborator CancellationBy { get; set; }
public DateTime? CancellationDate { get; set; }
public bool Active { get; set; }
public bool WhereAvailable { get; set; }
public bool RequestAsset { get; set; }
public string CityZone { get; set; }
public string TravelsTo { get; set; }
public string Description { get; set; }
public string SpecificationFile { get; set; }
public int PositionPriorityId { get; set; }
public int? SourcingGroupId { get; set; }
}
[Table("My_Opportunity_Table")]
public class Opportunity : ControlData
{
[Column("OpportunityId")]
[Key]
public int Id { get; set; }
[Column("OpportunityStatusId")]
public int StatusId { get; set; }
[ForeignKey("StatusId")]
public OpportunityStatus Status { get; set; }
public string ProjectId { get; set; }
[ForeignKey("ProjectId")]
public Project Project { get; set; }
public string MarketId { get; set; }
[ForeignKey("MarketId")]
public Market Market { get; set; }
public string CustomerId { get; set; }
[ForeignKey("CustomerId")]
public Customer Customer { get; set; }
public string Name { get; set; }
[Column("OpportunityTypeId")]
public int TypeId { get; set; }
[ForeignKey("TypeId")]
public OpportunityType Type { get; set; }
[Column("OpportunityPriorityId")]
public int PriorityId { get; set; }
[ForeignKey("PriorityId")]
public OpportunityPriority Priority { get; set; }
public int? OpportunityCancellationReasonId { get; set; }
[ForeignKey("OpportunityCancellationReasonId")]
public OpportunityCancellationReason CancellationReason { get; set; }
public string CancellationComments { get; set; }
public int? CancellationById { get; set; }
[ForeignKey("CancellationById")]
public Collaborator CancellationBy { get; set; }
public DateTime? CancellationDate { get; set; }
public bool Active { get; set; }
public List<OpportunityRole> OpportunityRoles { get; set; }
public List<Position> Positions { get; set; }
}
And also, I've got their equivalents in DTO's:
public abstract class ControlDataDTO
{
public DateTime CreatedDate { get; set; }
public int CreatedById { get; set; }
public CollaboratorPlainDTO CreatedBy { get; set; }
public DateTime? UpdatedDate { get; set; }
public int? UpdatedById { get; set; }
public CollaboratorPlainDTO UpdatedBy { get; set; }
}
public class PositionDTO: ControlDataDTO
{
public int Id { get; set; }
public int StatusId { get; set; }
public PositionStatusDTO Status { get; set; }
public int OpportunityId { get; set; }
public OpportunityDTO Opportunity { get; set; }
public int Total { get; set; }
public int DurationId { get; set; }
public PositionDurationDTO Duration { get; set; }
public DateTime StartDate { get; set; }
public string PracticeId { get; set; }
public PracticeDTO Practice { get; set; }
public int RoleId { get; set; }
public PersonRoleDTO Role { get; set; }
public int PlatformId { get; set; }
public PlatformDTO Platform { get; set; }
public int LevelId { get; set; }
public LevelDTO Level { get; set; }
public int EnglishLevelId { get; set; }
public EnglishLevelDTO EnglishLevel { get; set; }
public string CountryId { get; set; }
public int LocationId { get; set; }
public LocationDTO Location { get; set; }
public int? OfficeId { get; set; }
public int OperationId { get; set; }
public PersonDTO Operation { get; set; }
public string OperationIS { get; set; }
public bool WhereAvailable { get; set; }
public bool RequestAsset { get; set; }
public string CityZone { get; set; }
public string TravelsTo { get; set; }
public string Description { get; set; }
public int CandidatesAccepted { get; set; }
public int CandidatesRejected { get; set; }
public int CandidatesWaiting { get; set; }
public bool HasCandidatesWaiting { get; set; }
public int TotalCandidates { get; set; }
public string SpecificationFile { get; set; }
public int? EvaluatorId { get; set; }
public int? SourcerId { get; set; }
public CollaboratorDTO Sourcer { get; set; }
public int? SourcingGroupId { get; set; }
public PositionCancellationReasonDTO CancellationReason { get; set; }
}
public class OpportunityDTO: ControlDataDTO
{
public int Id { get; set; }
public int StatusId { get; set; }
public OpportunityStatusDTO Status { get; set; }
public string ProjectId { get; set; }
public ProjectDTO Project { get; set; }
public string MarketId { get; set; }
public MarketDTO Market { get; set; }
public string CustomerId { get; set; }
public CustomerDTO Customer { get; set; }
public string Name { get; set; }
public int TypeId { get; set; }
public OpportunityTypeDTO Type { get; set; }
public int PriorityId { get; set; }
public OpportunityPriorityDTO Priority { get; set; }
public int? OpportunityCancellationReasonId { get; set; }
public OpportunityCancellationReasonDTO CancellationReason { get; set; }
public string CancellationComments { get; set; }
public int? CancellationById { get; set; }
public CollaboratorPlainDTO CancellationBy { get; set; }
public DateTime? CancellationDate { get; set; }
public CollaboratorDTO Responsible { get; set; }
public List<OpportunityRoleDTO> OpportunityRoles { get; set; }
public int TotalPositions { get; set; }
public bool CandidatesWarning { get; set; }
public bool Active { get; set; }
public List<PositionDTO> Positions { get; set; }
}
For this mapping initialization we are using Profiles, like this way:
public class AutoMapperConfig
{
public static void RegisterMappings()
{
Mapper.Initialize(cfg =>
{
// ...
cfg.AddProfile<OpportunityMappingProfile>();
// ...
});
}
}
public class OpportunityMappingProfile : Profile
{
public OpportunityMappingProfile()
{
CreateMap<Opportunity, OpportunityDTO>()
.ForMember(x => x.Responsible, x => x.MapFrom(c => GetFromOpportunityRoles(c.OpportunityRoles, Constants.OpportunityResponsible)))
.ForMember(x => x.TotalPositions, x => x.MapFrom(c => c.Positions.Count()))
.ForMember(x => x.CandidatesWarning, x => x.MapFrom(c => c.Positions.Count() > 0 ?
c.Positions.Any(pos => pos.Candidates.Any(cand => cand.StatusId == 3)) :
false))
.ForMember(x => x.CreatedBy, x => x.MapFrom(c => Mapper.Map<CollaboratorPlainDTO>(c.CreatedBy)))
.ForMember(x => x.UpdatedBy, x => x.MapFrom(c => Mapper.Map<CollaboratorPlainDTO>(c.UpdatedBy)))
.ForMember(x => x.Positions, x => x.MapFrom(c => Mapper.Map<List<PositionDTO>>(c.Positions))).PreserveReferences(); --> Even using this method, StackOverflow exception is still occurring...
CreateMap<OpportunityDTO, Opportunity>()
.ForMember(x => x.CancellationReason, x => x.Ignore())
.ForMember(x => x.CreatedBy, x => x.Ignore())
.ForMember(x => x.UpdatedBy, x => x.Ignore())
.ForMember(x => x.Positions, x => x.Ignore());
}
private Collaborator GetFromOpportunityRoles(List<OpportunityRole> opportunityRoles, string rol)
{
var opportunityRole = opportunityRoles.FirstOrDefault(opp => opp.ProjectRoleTypeId == rol);
return opportunityRoles != null ? opportunityRole.Collaborator : null;
}
}
And finally, the logic that does the mapping where I'm getting the commented error...
public class OpportunityLogic : IOpportunityLogic
{
// Properties...
public OpportunityLogic(parameters list here, though irrelevant for this example)
{
// ...
}
public ActionResponse<List<OpportunityDTO>> GetOpportunitiesWithPositions(int personId)
{
// Information is retrieved from DB, here...
List<Opportunity> listOpportunities = opportunityRepository.Get(
opp => opp.Status,
opp => opp.Market,
opp => opp.Customer,
opp => opp.Type,
opp => opp.Project,
opp => opp.Status,
opp => opp.Positions,
opp => opp.Positions.Select(pos => pos.Candidates),
opp => opp.Positions.Select(pos => pos.Status),
opp => opp.Positions.Select(pos => pos.Practice),
opp => opp.Positions.Select(pos => pos.Role),
opp => opp.Positions.Select(pos => pos.Platform),
opp => opp.Positions.Select(pos => pos.Sourcer));
// After having retrieved data, here I re-define my model.
listOpportunities = listOpportunities
.Where( opp => opp.StatusId == (int)Constants.OpportunityStatus.Open &&
opp.Active == true &&
opp.Positions.Any(pos => pos.StatusId == (int)Constants.PositionStatus.Open &&
pos.Candidates.Any(can => can.PersonId == personId &&
can.Active == true &&
(can.StatusId == (int)Constants.CandidateStatus.Lead ||
can.StatusId == (int)Constants.CandidateStatus.Waiting))))
.ToList();
// MY PROBLEM IS HERE....
var mappedOpportunities = Mapper.Map<List<OpportunityDTO>>(listOpportunities);
return new ActionResponse<List<OpportunityDTO>> (mappedOpportunities);
}
}
My problem starts when trying to map my Model (List) to the DTO (List); the error is the well-known "StackOverflow Exception". If I'm using the "PreserveReferences()" method, why is still throwing the same exception?. The same goes for "MaxDepth() method", after having tried different depth levels (1,2,3...).
I've spent too many hours trying to solve this issue and to be honest, I'm out of ideas already. If anyone has an idea what to do here, I'll be really grateful.
Thanks and advance & regards!!
Starting from 6.1.0 PreserveReferences is set automatically at config time whenever the recursion can be detected statically. If that doesn't happen in your case, open an issue with a full repro and we'll look into it.
http://automapperdocs.readthedocs.io/en/latest/5.0-Upgrade-Guide.html#circular-references
But you have to remove the Map calls inside the MapFroms. Those ForMember-s are not needed.
The issue here is that I was missing another Mapping Profile that needed to preserve its references, but had not mentioned here, since I was missing that part and that was the one that had causing me all the issues.
This is my model:
public partial class DEGIVREUSE_SITE
{
public int EVENEMENT_ID { get; set; }
public string DEGIVREUSE_ID { get; set; }
public string SITE_COD { get; set; }
public string ETAT_GLOBAL { get; set; }
public string ETAT_CARBURANT { get; set; }
public Nullable<int> KM_CHASSIS { get; set; }
public Nullable<int> HEURE_CHASSIS { get; set; }
public string ETAT_FONCTIONNEMENT { get; set; }
public Nullable<int> HEURE_GROUPE { get; set; }
public string COMMENTAIRE { get; set; }
public virtual DEGIVREUSE DEGIVREUSE { get; set; }
public virtual SITE SITE { get; set; }
public virtual EVENEMENT EVENEMENT { get; set; }
}
[DataContract]
public class InventaireDegivreuse : Evenement
{
public InventaireDegivreuse()
: base(-1, Global.EvenementType.InventaireDegivreuse, DateTime.MinValue)
{
}
public InventaireDegivreuse(int id, DateTime date, string libelle, string societe)
: base(id, (int)Global.EvenementType.InventaireDegivreuse, date, libelle, "", "", societe)
{
ListeDegivreuses = new List<EtatDegivreuse>();
}
[DataMember]
public List<EtatDegivreuse> ListeDegivreuses { get; set; }
public void AddDegivreuse(EtatDegivreuse degivreuse)
{
lock (ListeDegivreuses)
ListeDegivreuses.Add(degivreuse);
}
public int NbDegivreuses
{
get
{
lock (ListeDegivreuses)
return ListeDegivreuses.Count;
}
}
public override void GenereLibelle()
{
Libelle = Properties.Resources.InventaireDegivreuse.Replace("%s", SocieteNom);
}
}
I need to orderby all Events with EVENEMENT_DT_CREA and after for each societe i get the first element of InventaireDegivreuse (the newer one which has the biggest EVENEMENT_DT_CREA) , I try this query but i had a bad result:
var #eventss = GetQuery(unitOfWork).Include(entity => entity.EVENEMENT).OrderByDescending(e => e.EVENEMENT.EVENEMENT_DT_CREA).GroupBy(m => m.EVENEMENT.SOCIETE_NOM).First().ToList();
In my solution for only one societe, i have correct result like this:
public InventaireDegivreuse GetLastBySociete(IReadOnlyUnitOfWork unitOfWork, string societeName)
{
var #event = GetQuery(unitOfWork).Include(entity => entity.EVENEMENT).OrderByDescending(e => e.EVENEMENT.EVENEMENT_DT_CREA).FirstOrDefault(m => m.EVENEMENT.SOCIETE_NOM ==societeName);
return DatabaseMapping.Map<DEGIVREUSE_SITE, InventaireDegivreuse>(#event);
}
Any idea please?
It will be hard to decide what do you want but I suspect that you want something like this:
var #event = GetQuery(unitOfWork)
.Include(entity => entity.EVENEMENT)
.GroupBy(e => e.EVENEMENT.SOCIETE_NOM)
.Select(g => g.OrderByDescending(e => e.EVENEMENT.EVENEMENT_DT_CREA)
.First());