InCorrect Map In AutoMapper When Map Model To ViewModel - c#

I Have an Model"TClientsAdmins" and ViewModel is TClientsAdminsViewModel.I want read all records from DB where filtered by id.
I Read they from domain model and when I want Map to viewmodel I get zero Count in viewmodel.
In addition I have a model that is called THoldingAdmins That is associated with TClientsAdmins.
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
[Key]
public int Id { get; set; }
[StringLength(50)]
public string CompanyName { get; set; }
public int? THoldingAdminsId { get; set; }
public virtual THoldingAdmins THoldingAdmins { get; set; }
and TClientAdminViewModel :
public int Id { get; set; }
[StringLength(50)]
public string CompanyName { get; set; }
public int? THoldingAdminsId { get; set; }
public virtual THoldingAdminsViewModel THoldingAdmins { get; set; }
and THoldingAdmins:
public byte[] Logo { get; set; }
public bool IsDeleted { get; set; }
public virtual List< TClientsAdmins> TClientsAdmins { get; set; }
and AutoMapper Configuration :
Mapper.CreateMap<TClientsAdminsViewModel, TClientsAdmins>();
Mapper.CreateMap<List<TClientsAdminsViewModel>,List<TClientsAdmins>>();

You don't need an explicit mapping for IList, but it does look like you have your mapping the wrong way round, if you're mapping from Model to ViewModel. Try
Mapper.CreateMap<TClientAdmins, TClientAdminsViewModel>();
Mapper.CreateMap<THoldingAdmins, THoldingAdminsViewModel>();

Related

Mapping self-referencing table data into another model (no automapper is used)

I have this table using Entity Framework code first approach :
public class WebsitePart
{
public WebsitePart()
{
SubParts = new HashSet<WebsitePart>();
}
[Key]
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public int Id { get; set; }
public Nullable<int> ParentId { get; set; }
[StringLength(100)]
[Index("UQ_WebsitePart_Key", IsUnique = true)]
public string Key { get; set; }
public virtual WebsitePart Parent { get; set; }
public virtual ICollection<WebsitePart> SubParts { get; set; }
}
I need after getting the list of WebsiteParts to map it into List of another model where each element of this list has ParentId=null and down to the end of its grandsons(traversing) .
This the model I want to map to:
public class WebPartViewDto
{
public int Id { get; set; }
public string Key { get; set; }
public IList<WebPartViewDto> SubWebParts { get; set; }
}
Could you please show me how to map it with performance is taken into account?

Entity Framework shared POCO

I have a bit of an issue and I need to know what the best design is for EF.
I have a Attribute model:
public enum TargetType
{
Attributes,
Availability,
Master
}
public class Attribute
{
public int Id { get; set; }
public int CriteriaId { get; set; }
[Required, MaxLength(100)] public string Name { get; set; }
[MaxLength(100)] public string Description { get; set; }
public TargetType Target { get; set; }
public virtual IList<Formula> Formulas { get; set; }
}
It has a list of Formulas:
public class Formula
{
public int Id { get; set; }
public int AttributeId { get; set; }
[Required]
[MaxLength(5)]
public string Operator { get; set; }
[Required]
[MaxLength(255)]
public string Expression { get; set; }
[MaxLength(100)]
public string Field { get; set; }
}
Which I match up in my DbContext like this:
modelBuilder.Entity<Attribute>().HasMany(m => m.Formulas).WithOptional().HasForeignKey(m => m.AttributeId);
The problem is, I now need to have Formulas as a separate property to another class Answer like this:
public class Answer
{
public int Id { get; set; }
public int QuestionId { get; set; }
[Required]
[MaxLength(255)]
public string Text { get; set; }
public int Order { get; set; }
public virtual IList<Formula> Formulas { get; set; }
}
The problem with this is Formula has AttributeId as a foreign key, so I can't really use the Formula model. I would have to create a new one like:
public class AnswerFormula
{
public int Id { get; set; }
public int AnswerId { get; set; }
[Required]
[MaxLength(5)]
public string Operator { get; set; }
[Required]
[MaxLength(255)]
public string Expression { get; set; }
[MaxLength(100)]
public string Field { get; set; }
}
But this seems counter-intuitive. So my question is, has anyone come across this before? If so, how did you solve the issue? For me, the problem is further enhanced when I start to use view models and factories.

Entity Framework 6 table with many foreign keys each pointing to different tables

I have Country, City, Region and "Account Address" tables.
I want to create foreign key columns in "Account Address" pointing to Country, City, Region tables.
I have this code but it throws an error on creating database
The property \u0027Account_Id\u0027 cannot be configured as a
navigation property. The property must be a valid entity type and the
property should have a non-abstract getter and setter. For collection
properties the type must implement
After New Edit
public class Cities
{
[Key]
public int City_Id { get; set; }
public string City_name { get; set; }
public int Country_Id { get; set; }
[ForeignKey("Country_Id")]
public Countries countries { get; set; }
}
public class Region
{
[Key]
public int Region_Id { get; set; }
public string Region_name { get; set; }
public int City_Id { get; set; }
[ForeignKey("City_Id")]
public Countries countries { get; set; }
}
public class Accounts
{
[Key]
public int Account_Id { get; set; }
public string Fullname { get; set; }
public string Email { get; set; }
public string password { get; set; }
public int Cell_phone { get; set; }
public string Role { get; set; }
public int? estate_office_Id { get; set; }
[ForeignKey("estate_office_Id")]
public Estate_office estate_office { get; set; }
public List<Ads> ads { get; set; }
}
public class Account_address
{
[Key]
public int Id { get; set; }
[ForeignKey("Account_Id"), Column(Order = 0)]
public int Account_Id { get; set; }
[ForeignKey("Country_Id"), Column(Order = 1)]
public int Country_Id { get; set; }
[ForeignKey("City_Id"), Column(Order = 2)]
public int City_Id { get; set; }
[ForeignKey("Region_Id"), Column(Order = 3)]
public int Region_Id { get; set; }
public Accounts accounts { get; set; }
public Countries countries { get; set; }
public Cities cities { get; set; }
public Region region { get; set; }
}
You need to define public properties as shown below on the Account_address class.Then only EF will know how to map those navigation properties correctly.
public class Account_address
{
......
......
public Accounts accounts { get; set; } //like this
public Countries countries { get; set; } //like this
public Cities cities { get; set; } //like this
public Region region { get; set; } //like this
}
Update :
Hence you're not using singular naming convention for the classes,you have encountered this issue.Either you have to change the name of classes as singular or need to change the navigational property names a shown below.You have to do this for all the places.Here I have shown only for the Accounts class related navigational property.
[ForeignKey("Accounts_Id"), Column(Order = 0)]
public int Accounts_Id { get; set; }
My Advice is to follow the basic naming conventions.Then you can avoid lot of above kind of weird errors.

How do I establish a one-to-one relationship using Database First?

When my models were generated, many relationships were mapped automagically. However, some of the relationships are "incorrect" (or at least, not what I want), or missing.
I don't doubt that this is because of poor database design, but based on my role in this project there is not much I can do to fix that. However, is there something I can do in my application code to fix the mapping?
Here is one example:
I would like to map the StoreProductId property to the StoreProducts table.
ProductAttributePriceAdjustment
public partial class ProductAttributePriceAdjustment
{
public int AdjustmentId { get; set; }
public int StoreProductId { get; set; }
public int StoreId { get; set; }
public string ProductId { get; set; }
public Nullable<int> ProductSizeId { get; set; }
public Nullable<decimal> Adjustment { get; set; }
public int PointsAdjustment { get; set; }
public Nullable<int> ProductColorID { get; set; }
public StoreProduct StoreProduct { get; set; }
}
StoreProduct
public partial class StoreProduct
{
public int StoreProductID { get; set; }
public int StoreID { get; set; }
public string ProductID { get; set; }
public bool Featured { get; set; }
public bool Clearance { get; set; }
}
In my view, when I try calling something like:
#adjustment.StoreProduct.ProductID
I get this error:
Object reference not set to an instance of an object.
Update 1
I followed Frans' advice and updated my model to this:
public partial class ProductAttributePriceAdjustment
{
public int AdjustmentId { get; set; }
public int StoreProductId { get; set; }
public int StoreId { get; set; }
public string ProductId { get; set; }
public Nullable<int> ProductSizeId { get; set; }
public Nullable<decimal> Adjustment { get; set; }
public int PointsAdjustment { get; set; }
public Nullable<int> ProductColorID { get; set; }
public virtual StoreProduct StoreProduct { get; set; }
}
but am still getting the same error.
You cannot create a 1:1 mapping in entity framework like this. It's not supported.
Entity Framework only supports 1:1 mappings in which both tables have a shared primary key (ie they have the same primary key, and one of them is a foreign key to the other). In your situation, you are actually creating a 1 to many, because there is no guarantee that StoreProductId is unique.

Relationships in Entity Framework Code First

yesterday I created database in Management Studio and now I want to create it in program using EF Code First.
Here is link to my database: http://s11.postimg.org/6sv6cucgj/1462037_646961388683482_1557326399_n.jpg
And what I did:
public class GameModel
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public DateTime CreationTime { get; set; }
public DateTime StartTime { get; set; }
public DateTime EndTime { get; set; }
public string TotalTime { get; set; }
public DateTime RouteStartTime { get; set; }
public DateTime RouteEndTime { get; set; }
public int MaxPlayersPerTeam { get; set; }
public int CityId { get; set; }
public int CreatorId { get; set; }
[InverseProperty("Id")]
[ForeignKey("CreatorId")]
//public int TeamId { get; set; }
//[ForeignKey("TeamId")]
public virtual UserModel Creator { get; set; }
public virtual CityModel City { get; set; }
//public virtual TeamModel WinnerTeam { get; set; }
}
public class RegionModel
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public virtual ICollection<CityModel> Cities { get; set; }
}
public class CityModel
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public int RegionId { get; set; }
public virtual RegionModel Region { get; set; }
public virtual ICollection<UserModel> Users { get; set; }
public virtual ICollection<GameModel> Games { get; set; }
}
public class UserModel
{
[Key]
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string Login { get; set; }
public string Password { get; set; }
public string Email { get; set; }
public DateTime RegistrationDate { get; set; }
public string FacebookId { get; set; }
public int CityId { get; set; }
public virtual CityModel City { get; set; }
public virtual IEnumerable<GameModel> Games { get; set; }
}
For now I wanted to create 4 tables but I have some problems... I want to make CreatorId in GameModel, but it doesn't work... When i wrote UserId instead of CreatorId it was working ( without [InverseProperty("Id")] and [ForeignKey("CreatorId")]).
This is what i get:
The view 'The property 'Id' cannot be configured as a navigation property. The property must be a valid entity type and the property should have a non-abstract getter and setter. For collection properties the type must implement ICollection where T is a valid entity type.' or its master was not found or no view engine supports the searched locations.
edit:
I changed it like this:
public int CityId { get; set; }
public int CreatorId { get; set; }
[ForeignKey("CityId")]
public virtual CityModel City { get; set; }
[ForeignKey("CreatorId")]
public virtual UserModel Creator { get; set; }
And there is another problem.
The view 'Introducing FOREIGN KEY constraint 'FK_dbo.UserModels_dbo.CityModels_CityId' on table 'UserModels' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints.
Could not create constraint. See previous errors.' or its master was not found or no view engine supports the searched locations.
And I have no idea how to solve it.
The InversePropertyAttribute specifies, which navigation property should be used for that relation.
A navigation property must be of an entity type (the types declared in your model, GameModel for example) or some type implementing ICollection<T>, where T has to be an entity type. UserModel.Id is an int, which clearly doesn't satisfy that condition.
So, the inverse property of GameModel.Creator could be UserModel.Games if you changed the type to ICollection<GameModel>, or had to be left unspecified. If you don't specify an inverse property, EF will try to work everything out on its own (in this case it would properly recognize GameModel.Creator as a navigation property, but UserModel.Games would most likely throw an exception, as it is neither an entity type, nor does it implement ICollection<T> with T being an entity type, nor is it a primitive type from a database point of view). However, EF's work-everything-out-by-itself-magic doesn't cope too well with multiple relations between the same entity types, which is when the InversePropertyAttribute is needed.
A quick example that demonstrates the problem:
class SomePrettyImportantStuff {
[Key]
public int ID { get; set; }
public int OtherId1 { get; set; }
public int OtherId2 { get; set; }
[ForeignKey("OtherId1")]
public virtual OtherImportantStuff Nav1 { get; set; }
[ForeignKey("OtherId2")]
public virtual OtherImportantStuff Nav2 { get; set; }
}
class OtherImportantStuff {
[Key]
public int ID { get; set; }
public virtual ICollection<SomePrettyImportantStuff> SoldStuff { get; set; }
public virtual ICollection<SomePrettyImportantStuff> BoughtStuff { get; set; }
}
Here, EF knows that it has to generate 2 FKs from SomePrettyImportantStuff to OtherImportantStuff with the names Id1 and Id2, but it has no way to tell which of the IDs refers to the entity where it was sold from and which is the one it was bought from.
Edit: How to fix the cyclic reference problem
To fix that problem, your context class should override OnModelCreating and configure the foreign keys which shouldn't cascade on delete accordingly, like this:
protected override void OnModelCreating(DbModelBuilder builder)
{
builder.Entity<CityModel>().HasMany(c => c.Users).WithRequired(u => u.City)
.HasForeignKey(u => u.CityId).WillCascadeOnDelete(value: false);
// Add other non-cascading FK declarations here
base.OnModelCreating(builder);
}

Categories

Resources