I have the following model:
public sealed class Consignor : TwoNames
{
public Consignor()
{
Address = new Address();
}
}
It's mother class TwoNames looks like this:
public abstract class TwoNames : Search
{
[Required]
public int AddressId { get; set; }
public virtual Address Address { get; set; }
[Required]
public string Name1 { get; set; }
public string Name2 { get; set; }
}
And my Address model is here:
public class Address : Model
{
[Required]
public string Street { get; set; }
[Required]
public string ZipCode { get; set; }
[Required]
public string City { get; set; }
public string Country { get; set; }
public string Email { get; set; }
}
They all inherit from "Model". Model has just an id.
Everything works well, BUT:
Lazy loading seems to be not working.
I'm loading a consignor like this:
List<Consignor> consignors = UnitOfWork.ConsignorRepository.Get().ToList();
All of the consignors got the correct AddressID and Address is not null (I guess because of my constructor in the Consignor class) but the Address property is not filled correctly (no street, no zip code, etc.).
It looks like the Consignor's constructor will instantiate a new Address object with blank street, zip, etc. (like you mentioned in your last paragraph); if you remove the instantiation of Address, you should end up with a not-loaded Address on your Consignor objects that you can lazily load as needed.
Related
Assuming I wan't to use single class to create and update an object in REST API - how I can do this without code duplication?
Create an object (POST) - all fields should be [Required].
Update an object (PATCH) - I want to use same class but fields should not be required as it can be done partially.
I can use below class for POST but can't for PATCH - as only Name may be updated (provided along the request) - which is OK.
public class Person
{
[Required]
public string Name { get; set; }
[Required]
public string LastName { get; set; }
}
The only solution I see (that causes code duplication) is:
public class CreatePerson
{
[Required]
public string Name { get; set; }
[Required]
public string LastName { get; set; }
}
public class UpdatePerson
{
public string Name { get; set; }
public string LastName { get; set; }
}
I am new to Automap, and I am trying to filter out the result. I want to know how to map nested dtos.
Post Entity:
public class Post
{
public Author? Author { get; set; }
[Required] [Key] public int Id { get; set; }
[Required] public string Title { get; set; }
[Required] public string Description { get; set; }
[Required] public string Body { get; set; }
}
PostRead: (dto)
public class PostRead
{
public DateTime Created { get; set; }
public string Title { get; set; }
public string Body { get; set; }
public string Description { get; set; }
// Author would work but I want only the AuthorRead data
public AuthorRead Author;
}
Author Entity
public class Author
{
[Key] [Required] public int Id { get; set; }
[Required] public string Name { get; set; }
public IEnumerable<Post> Posts { get; set; }
}
AuthorRead.cs (dto)
public class AuthorRead
{
public int Id { get; set; }
public string Name { get; set; }
}
Technically if I use Author Entity in PostRead, it works but it'll give the list of the posts the Author has, and i want only the information that is in the AuthorRead (so the API response doesn't send the list of posts of the Author itself).
how I can map the object of type Author to the type AuthorRead in the PostRead?
Errors:
AutoMapper.AutoMapperMappingException : Missing type map configuration or unsupported mapping.
Mapping types:
Object -> PostRead
System.Object -> OhMyBlogAPI.Models.PostRead
at lambda_method22(Closure , Object , PostRead , ResolutionContext )
at OhMyBlogAPI.Tests.AutomapTests.MockPost_MapsTo_PostRead() in
What I tried , and searching a lot.
CreateMap<Post, PostRead>()
.ForMember(m
=> m.Author, o
=> o.MapFrom<Author, AuthorRead>("Author"));
And profiles (each line represent relevant profiles content):
CreateMap<Post, PostRead>();
CreateMap<Author, AuthorRead>();
My bad, the code works.
I misconfigured something in the Unit testing. I am really sorry.
This should have come up like a million times by now, but I can't seem to find anything solid that I like.
Please, consider
public class Person
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Position { get; set; }
}
which appears twice in my view model
public class MyViewModel
{
public Person MainContact { get; set; }
public Person AltContact { get; set; }
}
Main contact is always required. Alternative contact is not required, but if anything is entered it should validate the entry. If I was to have 2 different Contact classes, they would be described like this:
public class MainContact
{
[Required]
[StringLength(50)]
string FirstName { get; set; }
[Required]
[StringLength(50)]
string LastName { get; set; }
string Position { get; set; }
}
public class AltContact
{
[StringLength(50)]
string FirstName { get; set; }
[StringLength(50)]
string LastName { get; set; }
string Position { get; set; }
}
But, I don't want to have 2 different Contact classes with the exactly same properties.
I would like one set of validations applied to one instance of Person class and another set of validations applied to a different instance of the same Person class. The solution also has to work with the client side validation with unobtrusive js turned on.
UPDATE 1: Added string Position to Person and Contact classes.
UPDATE 2: Thank you all for your inputs. Given time constraints and old UI requirements, I ended up with having 2 separate classes. However, I personally like Erik Funkenbusch's alternative approach from comments below. If I'll run into a similar situation in the future, I will push for the List of objects and the "Add New Bla" button solution. I think that's the way to go.
As the Null property answer doesn't seem to be working for you, I would suggest the following model then :
public class MainContact: BaseContact
{
[Required]
[StringLength(50)]
public override string FirstName { get; set; }
[Required]
[StringLength(50)]
public override string LastName { get; set; }
}
public class BaseContact
{
[StringLength(50)]
public virtual string FirstName { get; set; }
[StringLength(50)]
public virtual string LastName { get; set; }
string Position { get; set; }
}
and then make the MainModel like so :
public class MyViewModel
{
[Required]
public MainContact MainContact { get; set; }
public BaseContact AltContact { get; set; }
}
You still need to have two different models, but you get the benefit of sharing the common elements through inheritance.
I've noticed an issue with EF 6.1 code first. I have the following classes -
namespace Domain
{
public interface ISupportsOptimisticConcurrency
{
byte[] RowVersion { get; set; }
}
public class Entity : ISupportsOptimisticConcurrency
{
public int Id { get; set; }
[Timestamp]
public byte[] RowVersion { get; set; }
}
public class Lookup : Entity
{
public Lookup()
{
Description = string.Empty;
}
[Required]
[MaxLength(100)]
public string Name { get; set; }
[MaxLength(300)]
public string Description { get; set; }
}
public class GroupType : Lookup
{
}
public class Group:Entity
{
public Group()
{
GroupType = new GroupType();
}
[Required]
public string Name { get; set; }
[Required]
public Guid ExternalId { get; set; }
[Required]
public string Password { get; set; }
[Required]
public string MonitorEmail { get; set; }
public string UrlRequestEmail { get; set; }
public bool UsesDefaultOptions { get; set; }
[ForeignKey("GroupType")]
public int GroupTypeId { get; set; }
public virtual GroupType GroupType { get; set; }
}
}
I've written a typical Repository class for accessing data from DB. Now, when I try to find a Group by Id, and include the GroupType, the GroupType doesn't load properly, and the Name property of GroupType comes as null.
Interestingly, when I removed the Group constructor which initializes a new GroupType, things start working fine.
Could you please explain this behavior?
Note: This same scenario works fine with NHibernate as it is.
Thanks for the replies.
I think you have to remove the initialization logic in the Group constructor:
GroupType = new GroupType();
This probably overwrites the loaded data or does not even load it (because it already was instantiated), causing the GroupType property to be the instance that you initialized it with instead of the one in the database.
It may be the same issue as explained here.
Bear with me as I'm new to C# and programming in general.
I'm trying to define a complex type that is in the same table as the principle class. Basically, it's the good old User and Address example.
public class Customer
{
[Key]
public int customerId { get; set; }
//some attributes
public string street { get; set; }
public string city { get; set; }
public string province { get; set; }
public string country { get; set; }
public string postal { get; set; }
}
So I try to slice off the address information into its own class:
public class Customer
{
[Key]
public int customerId { get; set; }
//some attributes
public Address address { get; set; }
}
[ComplexType]
public class Address
{
public string street { get; set; }
public string city { get; set; }
public string province { get; set; }
public string country { get; set; }
public string postal { get; set; }
}
I get no compile error and when I load a view that access the Customer model, I get an unknown column in field set error.
Unknown column 'Extent1.address_street' in 'field list'
I basically followed this example: http://weblogs.asp.net/manavi/archive/2010/12/11/entity-association-mapping-with-code-first-part-1-one-to-one-associations.aspx
Is there something I"m missing or something different with EF5?
By default EF expects columns for properties of complex types in form {complextypename_propertyname}. If you created your tables manually and named columns differently there will be a mismatch. Can you try renaming the columns accordingly (i.e. street to address_street) and try if it works. Alternatively you should be able to add an attribute to the properties on the complex type to tell EF that is should not use the convention but the name you specified (e.g. [Column("street")] for the street property).