I need a help from you ...
I'm developing a solution using the Cassandra Data Base and DataStax driver for C# to generate POCO code to generate the column family to the database, the problem is that I'm mapping wanting to map a column that is a UDT dictionary and is not operating, below the code so that someone can help me ...
Maps.cs
For<Users>()
.TableName("Users")
.PartitionKey(key => key.UsersId)
.Column(u => u.UsersId, map => map.WithName("UsersId"))
.Column(u => u.ImgProfileUrl, map => map.WithName("ImgProfileUrl"))
.Column(u => u.Name, map => map.WithName("Name"))
.Column(u => u.Gender, map => map.WithName("Gender"))
.Column(u => u.UserName, map => map.WithName("UserName"))
.Column(u => u.UserPassword, map => map.WithName("UserPassword"))
.Column(u => u.DateOfBorn, map => map.WithName("DateOfBorn"))
.Column(u => u.OpeningDate, map => map.WithName("OpeningDate"))
.Column(u => u.FederalRegistrationCode, map => map.WithName("FederalRegistrationCode"))
.Column(u => u.StateRegistrationCode, map => map.WithName("StateRegistrationCode"))
.Column(u => u.TownRegistrationCode, map => map.WithName("TownRegistrationCode"))
.Column(u => u.Score, map => map.WithName("Score"))
.Column(u => u.Type, map => map.WithName("Type"))
.Column(u => u.Status, map => map.WithName("Status"))
.Column(u => u.DateOfCreated, map => map.WithName("DateOfCreated"))
.Column(u => u.Tags, map => map.WithName("Tags"))
.Column(u => u.Contacts, map => map.AsFrozen());
Entities Column Family
public class Users
{
public Guid UsersId { get; set; }
public string Name { get; set; }
public string ImgProfileUrl { get; set; }
public string UserName { get; set; }
public string UserPassword { get; set; }
public int? Gender { get; set; }
public DateTime? DateOfBorn { get; set; }
public DateTime? OpeningDate { get; set; }
public int Status { get; set; }
public string FederalRegistrationCode { get; set; }
public string StateRegistrationCode { get; set; }
public string TownRegistrationCode { get; set; }
public int Type { get; set; }
public int Score { get; set; }
public DateTime DateOfCreated { get; set; }
public IEnumerable<string> Tags { get; set; }
public IEnumerable<contactsudt> Contacts { get; set; }
}
Entities UDT
public class contactsudt
{
public string Phone { get; set; }
public string Celular { get; set; }
public string Address { get; set; }
public long Number { get; set; }
public string District { get; set; }
public string Postalcode { get; set; }
public string Name { get; set; }
public string State { get; set; }
public string Country { get; set; }
}
Configuration Instance
new Configuration<contactsudt, Users>();
new Table<Users>(UtilsDb.Session).CreateIfNotExists();
Make sure that you're registering your UDT with the session object whenever you bootstrap/create the session before you try to use it. For example, to use auto-mapping:
session.UserDefinedTypes.Define(
UdtMap.For<contactsudt>()
.Automap()
);
Also, make sure to register your maps (in Maps.cs in the example you gave) with the global MappingConfiguration so that LINQ will know about it:
MappingConfiguration.Global.Define<Maps>();
It sounds like you're probably missing the user defined type map.
Related
Via AutoMapper, I want to convert CreateUserInputModel to UserModel.
CreateUserInputModel has a property: List<int> Options which accepts IDs of options. UserModel has a property: List<OptionModel> Options which contains the list of OptionModel which has the field Id. I tried to create a mapper ForMember, but when I add it to the mapper, an unusual error appears without exception.
If you have any ideas on how to resolve this mapping, I will be very grateful. Thank you!
CreateUserInputModel
public class CreateUserInputModel
{
public string Email { get; set; } = string.Empty;
public string Firstname { get; set; } = string.Empty;
public string Lastname { get; set; } = string.Empty;
public DateTime EmploymentDate { get; set; }
public int WorkTypeId { get; set; }
public List<int>? Options { get; set; } = new List<int>();
}
UserModel
public class UserModel
{
public int Id { get; set; }
public string Email { get; set; } = string.Empty;
public string Password { get; set; } = string.Empty;
public string Firstname { get; set; } = string.Empty;
public string Lastname { get; set; } = string.Empty;
public int VacationDays { get; set; }
public DateTime EmploymentDate { get; set; }
public WorkTypeModel WorkType { get; set; } = new WorkTypeModel();
public List<OptionModel>? Options { get; set; } = new List<OptionModel>();
}
User mapper
CreateMap<UserModel, CreateUserInputModel>()
.ForMember(dest => dest.WorkTypeId, opt => opt.MapFrom(src => src.WorkType.Id))
.ForMember(dest => dest.Options, opt => opt.MapFrom(src => src.Options.Select(option => option.Id).ToList()))
.ReverseMap();
Think that you miss out on the mapping configuration for mapping from int to OptionModel and vice versa.
CreateMap<int, OptionModel>()
.AfterMap((src, dest) =>
{
dest.Id = src;
});
CreateMap<OptionModel, int>()
.ConstructUsing(src => src.Id);
Sample .NET Fiddle
I have two tables - Order and MenuItem with many-to-many relation.
public class Order
{
[Key]
public int OrderId { get; set; }
public DateTime OrderDate { get; set; }
public string Comments { get; set; }
public string OrderStatus { get; set; }
public string WaiterName { get; set; }
public double TotalPrice { get; set; }
public virtual ICollection<MenuItem> MenuItems { get; set; }
}
public class MenuItem
{
[Key]
public int MenuItemId { get; set; }
public string Name { get; set; }
public double Price { get; set; }
public int MenuItemTypeId { get; set; }
public MenuItemType MenuItemType { get; set; }
public virtual ICollection<Order> Orders { get; set; }
}
public class OrderMenuItem
{
public int MenuItemId { get; set; }
public int OrderId { get; set; }
public Order Order { get; set; }
public MenuItem MenuItem { get; set; }
}
modelBuilder.Entity<MenuItem>()
.HasMany(m => m.Orders)
.WithMany(o => o.MenuItems)
.UsingEntity<OrderMenuItem>(
x => x.HasOne(x => x.Order)
.WithMany().HasForeignKey(x => x.OrderId),
x => x.HasOne(x => x.MenuItem)
.WithMany().HasForeignKey(x => x.MenuItemId)
);
The question is how can I retrieve MenuItems that are in certain order and show the data using the ListView?
Just use the navigation property.
The simple and easy way would be
var order = await _context.Orders
.Where(o => ...)
.Include(o => o.MenuItems)
.FirstOrDefaultAsync();
and the proper way would be, one that also lets you filter and order the items would be
var order = await _context.Orders
.Where(o => ...)
.Select(o => new OrderDto {
Id = o.Id,
Status = o.Status,
// etc
Items = o.Items
.Where(i => ...)
.OrderBy(i => ...)
// etc
})
.FirstOrDefaultAsync();
And while we're at it, delete that virtual modifier. It's used for lazy loading, and what you want here is not lazy loading.
Just to tack on to what Angius posted:
var orderedMenuItems = dbContext.MenuItems.OrderBy(mi => mi.id).ToList();
Then just connect your list to your UI.
I have the following classes (One-One relationship Asset-TrackingDevice):
public class Asset
{
public int Id { get; set; }
public string Name { get; set; }
public TrackingDevice TrackingDevice { get; set; }
}
public class TrackingDevice
{
public int Id { get; set; }
public string Imei { get; set; }
public int? AssetId { get; set; }
public Asset Asset { get; set; }
}
The viewModels are very similar:
public class AssetViewModel
{
public int Id { get; set; }
public string Name { get; set; }
public int? TrackingDeviceId { get; set; }
public TrackingDeviceViewModel TrackingDevice { get; set; }
}
public class TrackingDeviceViewModel
{
public int Id { get; set; }
public string Imei { get; set; }
public AssetViewModel Asset { get; set; }
public string AssetId { get; set; }
}
Mappings:
CreateMap<Asset, AssetViewModel>()
.ForMember(d => d.TrackingDevice, map => map.Ignore());
CreateMap<AssetViewModel, Asset>()
.ForMember(d => d.TrackingDevice, map => map.Ignore());
CreateMap<AssetViewModel, Asset>()
.ReverseMap();
CreateMap<TrackingDevice, TrackingDeviceViewModel>()
.ForMember(d => d.Asset, map => map.Ignore());
CreateMap<TrackingDeviceViewModel, TrackingDevice>()
.ForMember(d => d.Asset, map => map.Ignore());
CreateMap<TrackingDevice, TrackingDeviceViewModel>()
.ReverseMap();
When I perform a database query to obtain the TrackingDevices,
I get an error because in the mapping the Asset within Tracking Device also includes a Tracking Device and so on.
The query that I execute to obtain the tracking devices is:
var trackingDevices = _appContext.TrackingDevices
.Include(td => td.Asset)
.ToListAsync();
var trackingMapper = Mapper.Map<IEnumerable<TrackingDeviceViewModel>>(trackingDevices);
I read that by including the Map.Ignore would fix the problem but it did not work either, does anyone know what my error is?
I want to combine 2 Domain Objects into a single data transfer object using AutoMapper.
Domain Model:
public class Service {
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public ICollection<DownloadService> DownloadServices { get; set; } = new HashSet<DownloadService>();
}
public class DownloadService {
public int Id { get; set; }
public int PageLimit { get; set; }
public virtual int ServiceId { get; set; }
public virtual Service Service { get; set; }
}
public class Volume {
public override int Id { get; set; }
public bool IsActive { get; set; }
public string Path { get; set; }
public string Description { get; set; }
}
DTO:
public class PreferenceVM {
public ICollection<VolumeVM> Volumes { get; set; }
public ICollection<ServiceVM> Services { get; set; }
}
public class ServiceVM {
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public ICollection<DownloadServiceVM> DownloadServices { get; set; } = new HashSet<DownloadServiceVM>();
}
public class DownloadServiceVM {
public int Id { get; set; }
public int PageLimit { get; set; }
public int CleaningInterval { get; set; }
}
public class VolumeVM {
public int Id { get; set; }
public bool IsActive { get; set; }
public string Path { get; set; }
public string Description { get; set; }
}
Mapping:
cfg.CreateMap<Volume, VolumeVM>().ReverseMap();
cfg.CreateMap<DownloadService, DownloadServiceVM>().ReverseMap();
cfg.CreateMap<Service, ServiceVM>()
.ForMember(d => d.DownloadServices, opt => opt.MapFrom(s => s.DownloadServices))
.ReverseMap();
cfg.CreateMap<ICollection<Volume>, PreferenceVM>()
.ForMember(x => x.Volumes, y => y.MapFrom(src => src)).ReverseMap();
cfg.CreateMap<ICollection<Service>, PreferenceVM>()
.ForMember(x => x.Services, y => y.MapFrom(src => src)).ReverseMap();
when I try the mapping above:
var services = serviceRepository.GetAll();
var volumes = volumeRepository.GetAll();
var entities = mapper.Map<PreferenceVM>(services);
entities = mapper.Map(volumes, entities);
I get the following errors:
Missing type map configuration or unsupported mapping.
Mapping types: EntityQueryable1 -> PreferenceVM
Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable1[[Fwims.Core.Data.Model.Setting.Service,
Fwims.Core.Data.Model, Version=1.0.1.10, Culture=neutral,
PublicKeyToken=null]] -> Fwims.Core.ViewModel.Setting.PreferenceVM
It looks like my mapping is wrong, nothing I have tried has worked. How do I properly map the Domain objects to the Data transfer objects?
Here
cfg.CreateMap<ICollection<Volume>, PreferenceVM>()
.ForMember(x => x.Volumes, y => y.MapFrom(src => src)).ReverseMap();
and
cfg.CreateMap<ICollection<Service>, PreferenceVM>()
.ForMember(x => x.Services, y => y.MapFrom(src => src)).ReverseMap();
you create mappings from ICollection<TSource>.
However later on you are trying to map IQeryable<TSource>. While AutoMapper can use a base mapping to map a derived class, IQueryable<T> does not derive from ICollection<T>, hence the missing type map exception.
The solution is to create a mapping from some common base interface of IQueryable<T> and ICollection<T>, which is IEnumerable<T>.
So replace the above with:
cfg.CreateMap<IEnumerable<Volume>, PreferenceVM>()
.ForMember(x => x.Volumes, y => y.MapFrom(src => src));
cfg.CreateMap<IEnumerable<Service>, PreferenceVM>()
.ForMember(x => x.Services, y => y.MapFrom(src => src));
and the current issue will be solved.
Note that ReverseMap does not work in such scenarios, so I've just removed it. If you need such functionality, you have to create that mappings manually (eventually using ConvertUsing because there is no destination member).
I'm trying to map my Box object to my BoxedElectrodesRowModel.
The Box object has a property SerialNumbers, and each of those has its own property of SerialNumberName. I'm trying to map that list of SerialNumberNames to a list of strings in my BoxedElectrodeRowModel called SerialNumbers.
AutoMapper code
c.CreateMap<Box, BoxedElectrodesRowModel>()
.ForMember(dest => dest.BoxId, opts => opts.MapFrom(src => src.BoxID))
.ForMember(dest => dest.SerialNumbers, opts => opts.MapFrom(src => src.SerialNumbers.Select(t => t.SerialNumberName).FirstOrDefault().ToList()))
.ForMember(dest => dest.DateCreated, opts => opts.MapFrom(src => src.DateCreated));
Here's the error I'm getting now. I don't know what "characters" it's referring to.
Missing map from System.Char to System.String. Create using
Mapper.CreateMap
The purpose of all of this is to create a table using DataTables that displays each Box with a list of its SerialNumbers on each row, if that helps. Everything is coded, but I keep getting the above error when it's run.
Edit: Here are my classes I'm mapping. I'm trying to map BoxId to BoxId, DateCreated to DateCreated, and the SerialNumberName from each SerialNumber (in a list) to SerialNumbers.
Box (Autogenerated)
public partial class Box
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public Box()
{
this.SerialNumbers = new HashSet<SerialNumber>();
}
public int BoxID { get; set; }
public System.DateTime DateCreated { get; set; }
public Nullable<System.DateTime> DateShipped { get; set; }
public string TrackingNumber { get; set; }
public Nullable<System.DateTime> DateReceived { get; set; }
public bool Active { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<SerialNumber> SerialNumbers { get; set; }
}
SerialNumber (This is a property of each 'Box', also autogenerated code)
public partial class SerialNumber
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
public SerialNumber()
{
this.Comments = new HashSet<Comment>();
this.WIPHistories = new HashSet<WIPHistory>();
}
public int SerialNumberID { get; set; }
public int IncomingLotID { get; set; }
public string SerialNumberName { get; set; }
public string LamPurchaseOrder { get; set; }
public string LamLineNumber { get; set; }
public bool Refurbished { get; set; }
public int WIPLocationID { get; set; }
public int StatusID { get; set; }
public int RouteSectionStepID { get; set; }
public Nullable<int> RejectCategoryID { get; set; }
public Nullable<int> BoxID { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<Comment> Comments { get; set; }
public virtual IncomingLot IncomingLot { get; set; }
public virtual RejectCategory RejectCategory { get; set; }
public virtual Status Status { get; set; }
public virtual WIPLocation WIPLocation { get; set; }
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
public virtual ICollection<WIPHistory> WIPHistories { get; set; }
public virtual Box Box { get; set; }
public virtual RouteSectionStep RouteSectionStep { get; set; }
}
BoxedElectrodesRowModel
public class BoxedElectrodesRowModel
{
public int BoxId { get; set; }
public List<string> SerialNumbers { get; set; } // change from List to ICollection if there are problems
public Nullable<System.DateTime> DateCreated { get; set; }
}
Your problem is FirstOrDefault() call. Because it returns only first string from serial number names. But string is IEnumerable<char>. When AutoMapper sees two enumerables, it tries to map them. In your case it will be IEnumerable<char> to IEnumerable<string>.
To fix this problem remove FirstOrDefault() call. Also thus AutoMapper knows how to map IEnumerable<T> to List<T> you don't need to create list manually.
opts => opts.MapFrom(src => src.SerialNumbers.Select(t => t.SerialNumberName))
I think the issue is highlighted in the error message.
Automapper is being told to map from a character object, System.Char, to a string object, System.String.
I believe the culprit is the call to FirstOrDefault(), which when called on a string, will return the first Char in the string:
src.SerialNumbers.Select(t => t.SerialNumberName).FirstOrDefault().ToList()
The select statement selects a String from the 'SerialNumbers' collection, which is what the 'MapFrom' call needs...so you don't need to call .FirstOrDefault or .ToList().
Remove them and see how this goes:
c.CreateMap<Box, BoxedElectrodesRowModel>()
.ForMember(dest => dest.BoxId, opts => opts.MapFrom(src => src.BoxID))
.ForMember(dest => dest.SerialNumbers, opts => opts.MapFrom(src => src.SerialNumbers.Select(t => t.SerialNumberName)))
.ForMember(dest => dest.DateCreated, opts => opts.MapFrom(src => src.DateCreated));
There is also another post about this issue:
AutoMapper: Collection to Single string Property