AutoMapper is Creating Duplicate Record in DB - entity-framework

It could be very basic question but i have stuck with this
I have an Entity Structure like this one below
public class OrderTagGroup : Entity
{
public virtual string Name { get; set; }
public virtual List<OrderTag> OrderTags { get; set; }
}
public class OrderTag : Entity
{
public virtual string Name { get; set; }
public virtual int? OrderTagGroupId { get; set; }
}
and Its respective DTO is
public class OrderTagGroupDto : EntityDto
{
[Required]
public string Name { get; set; }
public List<OrderTagDto> OrderTags { get; set; }
}
public class OrderTagDto : EntityDto
{
[Required]
public string Name { get; set; }
public int? OrderTagGroupId { get; set; }
}
I have added the Auto mapping as well like this
Mapper.CreateMap<OrderTagGroup, OrderTagGroupDto>();
Mapper.CreateMap<OrderTagGroupDto, OrderTagGroup>();
Mapper.CreateMap<OrderTag, OrderTagDto>();
Mapper.CreateMap<OrderTagDto, OrderTag>();
Here is my Repository update
public void UpdateOrderTagGroup(OrderTagGroupDto OrderTagGroup)
{
var group = _OrderTagGroupRepo.Get(OrderTagGroup.Id);
if (group != null && group.Id > 0)
{
Mapper.Map<OrderTagGroupDto, OrderTagGroup>(OrderTagGroup,group);
}
}
My Question is, whenever my OrderTagGroupDTO goes for the update, it creates a new row in the DB and previous entry is not deleted.
Could you please help me where i am wrong ?

Automapper is for entity->DTO ..
NEVER use automapper or similar for DTO->entity it's NOT designed for that
For DTO->entity you should 'always' do it 'manually'

Related

Entity Framework attempting to select non-existing column

I'm using Entity Framework 6.0 and have defined 2 POCO's to map to my database:
[Table("PortfolioGroups")]
public class PortfolioGroup : AuditableEntity<int>
{
[Column("Company_Id")]
public int CompanyId { get; set; }
[ForeignKey("CompanyId")]
public Company Company { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public ICollection<PortfolioGroupItem> PortfolioGroupItems { get; set; }
public PortfolioGroup()
{
PortfolioGroupItems = new Collection<PortfolioGroupItem>();
}
}
And the PortfolioGroupItem:
[Table("PortfolioGroupItems")]
public class PortfolioGroupItem : AuditableEntity<int>
{
[Column("PortfolioGroup_Id")]
public int PortfolioGroupId { get; set; }
[ForeignKey("PortfolioGroupId")]
public PortfolioGroup PortfolioGroup { get; set; }
[Column("Trademark_Id")]
public int? TrademarkId { get; set; }
[ForeignKey("TrademarkId")]
public Trademark.Trademark Trademark { get; set; }
[Column("TrademarkRegistration_Id")]
public int? TrademarkRegistrationId { get; set; }
[ForeignKey("TrademarkRegistrationId")]
public TrademarkRegistration TrademarkRegistration { get; set; }
[Column("Domain_Id")]
public int? DomainId { get; set; }
[ForeignKey("DomainId")]
public Domains.Domain Domain { get; set; }
}
However - when I attempt to query the PortfolioGroups, Entity Framework for some reason attempts to query a field named "Trademark_Id" - which doesn't exist on the PortfolioGroup entity:
Context.PortfolioGroups.SingleOrDefault(i => i.Id == id && i.CompanyId == companyId);
Throws:
Invalid column name 'Trademark_Id'.
I've used this kind of setup other places in my application without any problems. I simply cannot find out why EF is trying to query a column that's not in my entity!
Any suggestions would be greatly appreciated. I'm at the end of my rope here.
Thanks guys! :)
The problem is that you've added a Navigation Property on Trademark that requires a Foreign Key on Portfolio Group:
public class Trademark
{
[Key]
public int Id { get; set; }
[MaxLength(250)]
[Required]
public string Name { get; set; }
[MaxLength(150)]
public string Filename { get; set; }
public ICollection<PortfolioGroup> PortfolioGroups { get; set; }
public Trademark()
{
PortfolioGroups = new Collection<PortfolioGroup>();
}
}
EF expects PortfolioGorup to have a Trademark_ID column to store which PortfolioGroups are associated with a Trademark.

Parent object is null when getting child objects using Entity Framework

public class AcsBatchingDbContext : DbContext
{
public DbSet<CardHolder> CardHolders { get; set; }
public DbSet<AccessCard> AccessCards { get; set; }
}
public class CardHolder
{
public int CardHolderId { get; set; }
public ICollection<AccessCard> AccessCards { get; set; };
}
public class AccessCard
{
public int AccessCardId { get; set; }
public CardHolder CardHolder { get; set; }
}
When I try to get AccessCards
using (var db = new AcsBatchingDbContext())
{
var cards = db.AccessCards.ToList();
}
Where card.CardHolder = null
Why? Why EF doesnt grab the CardHolder?
Another question:
Why this expression doesnt compile?
db.AccessCards.Include(x => x.CardHolder).ToList();
Why the only options is to use is
db.AccessCards.Include("CardHolder").ToList();
You should use include to load CardHolder entity.
(This requires using System.Data.Entity;)
db.AccessCards.Include(x => x.CardHolder).ToList();
Alternatively, you can apply Include like this;
db.AccessCards.Include("CardHolder").ToList();

Entity Framework fails to get child elements

I have SQLite db and these EF models and context.
Models and Context
public class CardHolder
{
public int CardHolderId { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string PhoneNumber { get; set; }
public string EmailAddress { get; set; }
public string TenantName { get; set; }
public ICollection<AccessCard> AccessCards { get; set; }
}
public class AccessCard
{
public int AccessCardId { get; protected set; }
public CardHolder CardHolder { get; set; }
public DateTime ActivationDate { get; protected set; }
public bool ActivationProcessed { get; set; }
public DateTime? DeactivationDate { get; protected set; }
public string DeactivationReason { get; set; }
public bool DeactivationProcessed { get; set; }
}
public class MyContext : DbContext
{
public DbSet<CardHolder> CardHolders { get; set; }
public DbSet<AccessCard> AccessCards { get; set; }
}
And the Main program
class Program
{
static void Main(string[] args)
{
using (var db = new MyContext())
{
var cardHolders = db.CardHolders.Include("AccessCard").ToList();
}
}
}
Question1: Why do I get this exception
System.InvalidOperationException: 'A specified Include path is not
valid. The EntityType 'SQLiteDemo.Models.CardHolder' does not declare
a navigation property with the name 'AccessCard'.'
If I replace it with
var cardHolders = db.CardHolders.Include("AccessCards").ToList();
I get another error:
SQL logic error no such column: Extent2.CardHolder_CardHolderId
What is wrong with Entity Framework?
Question2: Why cant I use arrow function in Include statement, it doesnt compile at all?
var cardHolders = db.CardHolders.Include(x => x.AccessCards).ToList();
Question3: Why do I need to use Include at all if my ICollection association property AccessCards is NOT virtual - that means eager loading must work by itself!
Why the hell it is so problematic and buggy? Nothing works as it should :(
1 - You have a typo as you have already determined :)
1B - "SQL logic error no such column: Extent2.CardHolder_CardHolderId"
EF isn't finding your FK. You could add it to your AccessCard model:
public int CardHolderId { get; set; }
2 - You need to pull in the LINQ extensions. Make sure you have both of these using statements at the top:
using System.Data.Entity;
using System.Linq;
3 - You, like many others, are misunderstanding lazy loading. Eager loading still requires an Include() to fetch related data. Lazy loading only fetches the relations when you access them.

how to update .edmx file without effecting all the other model classes?

how to update .edmx file without effecting all the other model classes?
when I update the edmx file it recreates all the other classes and this is a problem for me because I made some changes on the other classes so how can I modify it without affecting the other classes.
For example this is one of my classes
public partial class company
{
public company()
{
this.Departments = new HashSet<department>();
this.CustomersOfTheCompany = new HashSet<company_customers>();
this.CompaniesTheCompanyCustomerFor = new HashSet<company_customers>();
this.CustomerProjectDetails = new HashSet<cus_pro_connector>();
this.CompanyAsSupplier = new HashSet<company_suppliers>();
this.CompanyAsCustomer = new HashSet<company_suppliers>();
this.Tickets = new HashSet<oneTimeAuthenticationTicket>();
}
[Required(ErrorMessage = "Company name is required")]
[StringLength(200, MinimumLength = 3, ErrorMessage = "Length Of The Company Name Should Be More Than Three Letters")]
public string CompanyName { get; set; }
[Required]
[EmailAddress(ErrorMessage = "Invalid Email Address")]
public string Email { get; set; }
[Required]
public int Country { get; set; }
public int company_id { get; set; }
public string Logo { get; set; }
public string Description { get; set; }
private CompanyDTO _CDTO = new CompanyDTO();
public CompanyDTO CDTO { get { return this._CDTO; } set { this._CDTO = value; } }
public virtual ICollection<department> Departments { get; set; }
public virtual country CountryOfTheCompany { get; set; }
public virtual ICollection<company_customers> CustomersOfTheCompany { get; set; }
public virtual ICollection<company_customers> CompaniesTheCompanyCustomerFor { get; set; }
public virtual ICollection<cus_pro_connector> CustomerProjectDetails { get; set; }
public virtual ICollection<company_suppliers> CompanyAsSupplier { get; set; }
public virtual ICollection<company_suppliers> CompanyAsCustomer { get; set; }
public virtual ICollection<oneTimeAuthenticationTicket> Tickets { get; set; }
}
so when I modify the .edmx the class attributes will no longer be available.
It is not possible to retain edits to generated files when you re-generate them. If you need to apply attributes to generated code, there is a MetadataType mechanism that allows you to specify validation attributes in another partial class.
See this other answer or MSDN for further information on this.
I don't understand your example - But I will explain here:
Let's say you have the following Entity Models:
And the User.cs looks like this:
public partial class User
{
public User()
{
this.UserWindows = new HashSet<UserWindow>();
}
public int UserId { get; set; }
public string UserName { get; set; }
public string Password { get; set; }
public virtual ICollection<UserWindow> UserWindows { get; set; }
}
Add a new file and call it Extensions.cs, then create a New Partial Class in this File:
Then you can Add Properties to this Class:
public partial class User
{
public int NewUserId { get; set; }
}
And whenever you create a New User Object you will see your new Properties:
Similarly you can do this for UserWindow.cs
Extensions.cs:
public partial class User
{
public int NewUserId { get; set; }
}
// Similarly you can do
public partial class UserWindow
{
public string MyNewProperty { get; set; }
}
Then

I get UpdateException when i try to Update a collection property

I am in an MVC4 application and i am using EF CodeFirst.
When I try to run the following code:
public void Autorizare(int cerereId, Persoana persoana)
{
var cerere = _db.Cereri.Find(cerereId);
cerere.Autorizare.Add(persoana);
_db.SaveChanges();
}
I get an error like this:
Entities in 'CerereDbContext.Persoane' participate in the 'Actiune_Executanti' relationship. 0 related 'Actiune_Executanti_Source' were found. 1 'Actiune_Executanti_Source' is expected.
i have tried Entity(Actiune).State = EntityState.Modified, but no results.
I have a main POCO:
public class Cerere
{
public int Id { get; set; }
...
public virtual ICollection<Actiune> Actiuni { get; set; }
...
}
the Actiune class looks like this
public class Actiune
{
public int Id { get; set; }
public DateTime Data { get; set; }
public String Nume { get; set; }
public virtual ICollection<Persoana> Executanti { get; set; }
public String Stadiu { get; set; }
public String Obs { get; set; }
}
And Persoana:
public class Persoana
{
public int Id { get; set; }
public DateTime Data { get; set; }
public String Nume { get; set; }
}
From your model the Cerere does not have a property named Autorizare; however it does have one named Actiuni. Which is of type Actiune not Persoana which is what you are trying to add to it. Please post the rest of the Class Definition.