I have the following:
public class SomeClass {
public Guid Id { get; set; }
public string Name { get; set; }
// Instead of having
public IEnumerable<Tag> Tags { get; set; }
// I want something like this
public IEnumerable<string> Tags { get; set; }
// more properties here
}
public class Tag {
public Guid Id { get; set; }
public string Name { get; set; }
// I put this here just to show you what I want,
// normally EF Core will generate this for me
public Guid SomeClassId { get; set; }
}
Is it possible to create the above scneario?
I know a good and maybe even better way to do this would be a Many-To-Many Relationship. But it would be neat to just add a new tag to the list and let EF take care of the rest of it.
I know there is Value Conversions, but I can't figure out if it is possible to apply it in this scenario. If I recall correctly you can do something like this in EF 6 with some custom mapping, but I don't see any version to do it in EF-Core.
Thanks in advance.
Related
I am working with AutoMapper, which I am relatively new with, and I stumbled upon a small mapping problem I was hoping the community could assist with.
So I have two data transfer objects:
public class UserDto {
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
public List<CharacterDto> Characters { get; set; }
}
public class CharaterDto {
public string CharacterName { get; set; }
public string ClassName { get; set; }
public int CharacterLevel { get; set; }
}
and two Domain Entities
public class Character {
public int ID { get; set; }
public int UserId { get; set; }
public string CharacterName { get; set; }
public string ClassName { get; set; }
public int CharacterLevel { get; set; }
}
public class User {
public int ID { get; set; }
public string UserName { get; set; }
public string FirstName { get; set; }
public string LastName { get; set; }
}
The end goal is to be able to save the data taken in by the DTOs into the database via the Domain Entities; however, when it comes to typing up the list of Characters for 'UserDto', I do not know how to map this properly with AutoMapper. I can map it manually with little to no problems... but I can't find anything that helps to explain this or any examples that would help me understand it better.
I have tried doing things like:
CreateMap<UserDto, Character>()
.ForMember(dest => dest.CharacterName, m => m.MapFrom(source => source.Characters[0].CharacterName));
However, this seems to only map the 1st entry and not the others. I have also considered mapping the individual mappings like so:
CreateMap<CharacterDto, Character>();
CreateMap<UserDto, Character>()
.ForMember(?/*this section I cannot figure out*/)
But can't figure out how to associate the the collection of characters to the mapped CharacterDto. I doubt that if I run the code without that association, the code is going to automatically understand that for each character in characters, map each character using the appropriate mapper... If I must manually do this, I can... but if there is an AutoMapper way, any help constructing it would be greatly appreciated.
Type converters are you friend here for mapping 1 to many like this.
Let me know if you need me to go further and get you a working example from your models.
https://stackoverflow.com/a/18096914/7911333
I am creating some view models for my ASP MVC web app.
I created "code first" models for database. Is it a good way to derive view models from database models?
Example database model:
public class Project
{
[Key]
public int Id { get; set; }
public int? CustomerId { get; set; }
public int TypeId { get; set; }
public string Number { get; set; }
public string Name { get; set; }
}
View model:
public class ViewModelProject : Project
{
[NotMapped]
public DateTime? Start { get; set; }
[NotMapped]
public DateTime? End { get; set; }
[NotMapped]
public string Manager { get; set; }
}
Is this the right way or is it completely false?
EDIT (subquestion):
I have some very simple database models like ProjectType, which only contains i.e. two properties. Should I also fragment those models in model view or can I make it that way:
Simple database model:
public class ProjectType
{
[Key]
public int Id { get; set; }
public string Name { get; set; }
public int? Code { get; set; }
}
Can I use it like so:
public class ProjectVM
{
public string Name { get; set; }
public int Number { get; set; }
public ProjectType Type { get; set; }
}
Or does it have to be fragmented like so:
public class ProjectVM
{
public string Name { get; set; }
public int Number { get; set; }
public string Type { get; set; }
public int TypeCode { get; set; }
}
I would not recommend doing it this way. I (and many others) have tried it and it doesn't work well. You will inadvertedly run into troubles, since an MVC model has to be tailored to the view and what you get from the DB rarely fits. Sure, you can hammer it into place, but the code quickly gets messy and store-related and UI code starts to mangle together. This even shows in your example, since you have to put the NotMappedAttribute (which is related to data storage), to ViewModelProject (a class at UI level).
There are many other examples to show this problem, but an especially good one I find when you want to serialize a model object to JSON and send it to a JavaScript client. The JSON serializer takes the values of all public properties and adds them to the JSON. If you want to exclude a property, you have to mark it with a ScriptIgnoreAttribute, which you would also have to apply to the base class, which breaks separation between UI and store-related code.
The better way to go is to keep the staorage model and the MVC model separated and to map the data from one to the other (there are already pre-existing frameworks that help you with that, such as Automapper). This comes with additional advantages, for example better testability, since you are now not dependent on a specific data store to create model instances.
After trying to execute the following query:
List<CourseLesson> courseLessons = (from cl in context.CourseLessons
.Include(x => x.CourseLessonTestQuestions)
select cl).ToList();
I get the the error Invalid column name 'CourseLesson_Id'.
My models and DataContext looks like this(this is from a test project I've created to repreduce the problem)
public class CourseLesson
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public ICollection<CourseLessonTestQuestion> CourseLessonTestQuestions { get; set; }
}
public class CourseLessonTestQuestion
{
public int Id { get; set; }
public int CourseLessonId { get; set; }
[ForeignKey(nameof(CourseLessonId))]
public CourseLesson CourseLesson { get; set; }
public int? ReturnCourseLessonId { get; set; }
[ForeignKey(nameof(ReturnCourseLessonId))]
public CourseLesson ReturnCourseLesson { get; set; }
}
I have 2 foreign keys that point to the same table and I'm assuming EF is trying to create or map something that doesn't really exist.
After reading for a while I've found a way to fix my problem in (this answer) with the following code:
modelBuilder.Entity<CourseLessonTestQuestion>()
.HasOptional(cltq => cltq.ReturnCourseLesson)
.WithMany(x => x.CourseLessonTestQuestions);
What really bugs me about this situation is why everything works when I use the Fluent API, but it doesn't work with the ForeignKey attribute? This looks like something that could lead to future problems and I want to know what is really happening.
And the real question is there a solution for fixing this problem without the Fluent API? Like using attributes or some other convention?
I'm using Entity Framework 6.1.3
Solution without Fluent API, but with the help of InversePropertyAttribute, whose constructor's argument is the name of corresponding CourseLessonTestQuestion's property:
public class CourseLesson
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
[InverseProperty("CourseLesson")]
public ICollection<CourseLessonTestQuestion> CourseLessonTestQuestions { get; set; }
[InverseProperty("ReturnCourseLesson")]
public ICollection<CourseLessonTestQuestion> ReturnCourseLessons { get; set; }
}
My Domain Classes is as follow:
public class Author
{
public int Id { get; set; }
public string Name { get; set; }
public IList<Post> Posts { get; set; }
}
public class Blog
{
public int Id { get; set; }
public string Name { get; set; }
public IList<Post> Posts { get; set; }
}
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public Author Author { get; set; }
public Blog Blog { get; set; }
}
As you see I have absolutely not any data annotation or attributes for entity framework annotations, and I Configure Entity framework related annotations in another classes for each one using entity framework fluent api.
now I want to replace entity framework with MangoDb.
but in mongo db I needed to place an attribute at list for Id like below:
public class Author
{
[BsonElement("_id")]
[BsonRepresentation(BsonType.ObjectId)]
public int Id { get; set; }
public string Name { get; set; }
public IList<Post> Posts { get; set; }
}
My Question is is there any way to this configuration outside in another class, and don't touch my poco classes like what we use in entity framework's fluent api.
You can do that by using a BsonClassMap class like:
BsonClassMap.RegisterClassMap<Post>(cm =>
{
cm.MapMember(x => x.Title).SetElementName("_title");
});
The documentatins is here: Mapping Classes
Also there are default conventions, and for Id field you don't need to map it to _id name, it will be handled automatically.
Basically you can use both EntityFramework and MongoDB driver attributes together. But I would not recommend you to use absolutely same data structure that you used in EntityFramework as SQL and NoSQL are completely different approaches. With NoSQL you should think more of how your application is going to consume your data and create your domain, chose optimal embedding strategy and apply indexes accordingly.
You can find some good reading on MongoDB website. Here are some links to start:
http://docs.mongodb.org/manual/core/data-model-design/
http://docs.mongodb.org/manual/core/data-modeling-introduction/
This is my first question on this community, I hope someone can help.
I have 3 models: Parent, child and grandchild. Resource, Parameter and Metric. I create the controlers with entity framework and it generated all CRUD operations. My problem its basically the grandchild. When I go to create a new Metric (grandchild), I have the dropdownlist of all the Parameters (child), but I want first to choose the Resource, then that will list all the parameters from that resource so I can create the metric. I'm new on asp MVC and this might be a lil bit basic question but I couldn't find anything like this. Thanks
Here are my classes just in case.
public class Resource
{
public int ResourceID { get; set; }
public string Name { get; set; }
public virtual ICollection<Parameter> Parameters { get; set; }
}
public class Parameter
{
public int ParameterID { get; set; }
public string Name { get; set; }
public int ResourceID { get; set; }
public virtual Resource Resource { get; set; }
public virtual ICollection<Metric> Metrics { get; set; }
}
public class Metric
{
public int MetricID { get; set; }
public string Name { get; set; }
public int ParameterID { get; set; }
public virtual Parameter Parameter { get; set; }
}
What you are trying to do sounds like either a linked or cascading drop down list. I did a quick search and found this link that may help you.
You will need some JavaScript that listens to the selection changed event for the first list (parent), and then updates the second list (child) with the available values. Depending on your situation, you may then need to link the third list (grandchild) to load when the second list has its selection changed as well.