No suitable constructor error in Entity Framework - entity-framework

So previously I failed to have a suitable constructor, because of naming violation. This time the naming is identical, yet it still fails.
I get the following error code:
No suitable constructor was found for entity type 'Customer'. The following constructors had parameters that could not be bound to properties of the entity type: cannot bind 'Address' in 'Customer(string firstName, string lastName, Address Address, string email)'.'
With the following execution:
using (var db = new EshopContext())
{
var test = db.Products
.Where(p => p.Title == customSearchTag)
.ToList(); //Error here
foreach (var item in test)
{
Console.WriteLine(item.Title + " for " + item.Price);
}
}
Address.cs
public int Id { get; set; }
public string Street { get; set; }
public string Zipcode { get; set; }
public string City { get; set; }
public string Country { get; set; }
public Address(string street, string zipcode, string city, string country)
{
Street = street;
Zipcode = zipcode;
City = city;
Country = country;
}
Customer.cs
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
public string Email { get; set; }
public Customer(string firstName, string lastName, Address Address, string email)
{
FirstName = firstName;
LastName = lastName;
this.Address = Address;
Email = email;
}
I hope someone can tell my why this error happens. Because I don't know why it won't bind the property

You need to add an empty constructor to avoid that error.
public class Company
{
public int Id { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public Address Address { get; set; }
public string Email { get; set; }
public Customer(string firstName, string lastName, Address Address, string email)
{
FirstName = firstName;
LastName = lastName;
this.Address = Address;
Email = email;
}
// Add this
public Customer() {}
}

Related

How to include related table column names in dynamic linq expressions?

I am using a dynamic linq expressions to filter my records. All works well, if i give the column names which are there in the model. But when i try to give the column name in related table, it breaks. Can anyone please help here
Model
public class User
{
public int UserID { get; set; }
public string FirstName { get; set; } = string.Empty;
public string LastName { get; set; } = string.Empty;
public UserRole Role { get; set; }
public int RoleID { get; set; }
}
public class UserRole
{
public int RoleID { get; set; }
public string RoleName { get; set; } = String.Empty;
}
ParameterExpression param = Expression.Parameter(typeof(User), "t");
con = Expression.Equal(Expression.Property(param, "Role.RoleName"), Expression.Constant("Admin"));
var deleg = Expression.Lambda<Func<User, bool>>(con, param);
var users= context.UserModel.Include(r => r.Role).Where(deleg).AsQueryable();

EF Core + Cosmos Db - some constructor parameters map but not others do not

I have the following class and data in Cosmos Db. When retrieving the data from the data store, some of the properties don't exist in the stored data and EF will map them as null (such as MiddleName) but the DateOfBirth and PhysicalAddress parameters throw a "Nullable object must have a value." error. I can't find out why the User parameters are being handled differently. I want any missing properties to be set to null if undefined/unavailable in the data store.
public class User
{
private User(UserId userId, IdpId idpId, string firstName, string middleName, string lastName, string suffix,
string email, string phoneNumber, DateOnly dateOfBirth)
{
UserId = userId;
IdpId = idpId;
FirstName = firstName;
MiddleName = middleName;
LastName = lastName;
Suffix = suffix;
Email = email;
PhoneNumber = phoneNumber;
DateOfBirth = dateOfBirth;
}
public UserId UserId { get; } = UserId.New();
public IdpId IdpId { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string Suffix { get; set; }
public string Email { get; set; }
public Address PhysicalAddress { get; set; }
public string PhoneNumber { get; set; }
public DateOnly DateOfBirth { get; set; }
public string ETag { get; set; }
}
public class Address
{
public string StreetLine1 { get; init; }
public string StreetLine2 { get; init; }
public string City { get; init; }
public string State { get; init; }
public static string Country => "US";
public string PostalCode { get; init; }
}
Item stored in Cosmos db
{
"UserId": "C8282366-A13C-48DF-9893-A5400DD73264",
"Created": "2021-06-27T12:09:54.556736-04:00",
"CreatedBy": "C8282366-A13C-48DF-9893-A5400DD73264#clients",
"Discriminator": "User",
"Email": "bob#bob.com",
"FirstName": "Bob",
"IdpId": "google-oauth2|111111111111111111111",
"LastModified": "2021-06-28T22:16:39.068558-04:00",
"LastModifiedBy": "C8282366-A13C-48DF-9893-A5400DD73264#clients",
"LastName": "King",
"id": "User|C8282366-A13C-48DF-9893-A5400DD73264"
}
Call to retrieve the all users
var userList = await _dbContext.Users.ToListAsync(cancellationToken);
For anyone that may run into this issue. The DateOnly property needed to be marked as nullable in the constructor and in the record class. The Address property cannot be used in constructor binding. See: Entity types with constructors
Final record class:
public record User
{
private User(UserId userId, IdpId idpId, string firstName, string middleName, string lastName, string suffix,
string email, string phoneNumber, DateOnly? dateOfBirth)
{
UserId = userId;
IdpId = idpId;
FirstName = firstName;
MiddleName = middleName;
LastName = lastName;
Suffix = suffix;
Email = email;
PhoneNumber = phoneNumber;
DateOfBirth = dateOfBirth;
}
public UserId UserId { get; } = UserId.New();
public IdpId IdpId { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string Suffix { get; set; }
public string Email { get; set; }
public Address PhysicalAddress { get; set; }
public string PhoneNumber { get; set; }
public DateOnly? DateOfBirth { get; set; }
public string ETag { get; set; }
}

AutoMapper returns null for all values in simple mapping case

I am using Entity Framework 6 with MVC and Web API and I have been toying with whether to use Data Transfer Objects (DTO's) for the JSON api side of things..
I came across AutoMapper and having written some DTO's manually thought (still think) this should be a good way to manage the DTO's.
So, New to it, installed via Nuget, I tried my first mapping. The mblUser class derived from IdentityUser as the source, and I want a simple APIUser to go down the wire..heres the classes:
public class mblUser : IdentityUser
{
public async Task<ClaimsIdentity> GenerateUserIdentityAsync(UserManager<mblUser> manager, string authenticationType = DefaultAuthenticationTypes.ApplicationCookie)
{
//authentication type added to provide for Bearer type of authentication. Still defaults to cookie though so as not to impact the code
// Note the authenticationType must match the one defined in CookieAuthenticationOptions.AuthenticationType
var userIdentity = await manager.CreateIdentityAsync(this, authenticationType );
// Add custom user claims here
return userIdentity;
}
[Display(Name = "Date of Birth IDVIEW")]
[DataType(DataType.DateTime)]
[DisplayFormat(DataFormatString = "{0:d}",
NullDisplayText = "Please Enter Your Date of Birth",
ApplyFormatInEditMode = true)]
public DateTime? DateOfBirth { get; set; }
public string Title { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName {get; set;}
public string DisplayName { get; set; }
public virtual Leader Leader { get; set;}
public virtual Guardian Guardian { get; set; }
public virtual Participant Participant { get; set; }
[NotMapped]
[Display(Name ="Full Name")]
public string FullName
{
get
{
return FirstName + (MiddleName !=null ? " " + MiddleName : "") + (LastName != null ? " " + LastName :"");
}
}
[NotMapped]
[Display(Name ="Details Complete")]
public bool DetailsComplete
{
get
{
if (string.IsNullOrEmpty(FullName.Trim()) || string.IsNullOrEmpty(Email) )
{
// set true if we have something of a name and an email address..
return false;
}
else
{
return true;
}
}
}
}
.. and heres the APIUser:
public class APIUser
{
private string Id { get; set; }
private string Email { get; set; }
private string UserName { get; set; }
private string Title { get; set; }
private string FirstName { get; set; }
private string MiddleName { get; set; }
private string LastName { get; set; }
private string DisplayName { get; set; }
private string PhoneNumber { get; set; }
}
... and heres the mapping code:
// GET: api/userSettings/5
[ResponseType(typeof(APIUser))]
public async Task<IHttpActionResult> GetmblUser(string username)
{
mblUser User = await UserManager.FindByNameAsync(username);
if (User == null)
{
return NotFound();
}
Mapper.CreateMap<mblUser, APIUser>();
APIUser dto = Mapper.Map<APIUser>(User); <-- here all User members are valid and populated.
return Ok(dto); <--at a breakpoint here.. all dto members are null.
}
I figure I must be doing some kind of Newbie error or something but cant figure out what? I did wonder if it is because the mblUser is derived from IdentityUser but the documentation is far from clear on that issue.
Out of interest, I did spot another issue that seems related here and I do indeed have AutoMapper.Net4 in my references as well as AutoMapper, but I have also seen that it is required elsewhere, so am a bit stuck ..
Any help would be appreciated.
You need to make your properties public before they can be mapped.
public class APIUser
{
public string Id { get; set; }
public string Email { get; set; }
public string UserName { get; set; }
public string Title { get; set; }
public string FirstName { get; set; }
public string MiddleName { get; set; }
public string LastName { get; set; }
public string DisplayName { get; set; }
public string PhoneNumber { get; set; }
}

EF6 Code First Relationship (MVC 5 app)

I have following classes
public class Address
{
public int ID { get; set; }
public AddressType AddressType { get; set; } // ( Enum -- {Correspondence, Billing, Other}
public string AddressLine {get; set;}
public string Town {get; set;}
public string Region {get; set;}
public string PostCode { get; set; }
public string Country {get; set;}
}
}
public class Company
{
[Key]
public int ID { get; set; }
public string LegalName { get; set; }
public string RegistrationNumber { get; set; }
public List<Address> Addresses { get; set; } // Addresses (Correspondence, billing address,physicalAddress etc)
}
public class Person
{
public int ID { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public string EmailAddress { get; set; }
public List<Address> Addresses { get; set; }
}
public ActionResult AddCompany()
{
Company Co = new Company();
Address postAddress = new Address() { AddressType = Helper.Enums.AddressType.PostAddress };
Address physicalAddress = new Address() { AddressType = Helper.Enums.AddressType.PhysicalAddress };
org.Addresses = new List<Address>();
org.Addresses.Add(postAddress);
org.Addresses.Add(physicalAddress);
}
I want Address to be added when ever I add Person or Company, but could not do so using Seed method.
EF creates CompanyID in Addresses table why, I want only one way relations, please help

how to concatenate first name and last name and display as full name in view when EF databasefirst

I want to concatenate first name and last name and display it as fullname in view.i tried in usermeta because when you again generate edmx file it will wont affect but error unrecognised fields,any idea how?
public partial class userdetail
{
public userdetail()
{
this.orderdetails = new HashSet<orderdetail>();
}
public string userid { get; set; }
public string username { get; set; }
public string firstname { get; set; }
public string lastname { get; set; }
public virtual ICollection<orderdetail> orderdetails { get; set; }
}
I created one more class usermeta for validations.
public class Usemeta
{
[Required]
public string userid { get; set; }
[Required]
public string username { get; set; }
[Required]
public string firstname { get; set; }
[Required]
public string lastname { get; set; }
//[Required]
//public string Fullname { get { return string.Concat(firstname + "" + lastname); } }
}
And then I created a partial class.
[MetadataType(typeof(Usemeta))]
public partial class userdetail
{
}
Just add another property in your View and concatenate FirstName and LastName as a read only property , Somthing like this :
public string FullName
{
get { return FirstName + " " +LastName ;}
}
Also you can use expression body:
public string FullName => FirstName + " " + LastName;