Automapper and EFCore Join - linq

I have to tables I want to Join which I can do with just EFCore but I can't figure out how to also use automapper.
So if I have two Classes
public class ItemVM {
public int Id {get; set;}
public int ItemName { get; set; }
public int GroupId {get; set;}
}
public class GroupVM {
public int Id {get; set;}
public string GroupName {get; set;}
}
And I want to end up with:
public class ItemWithGroupVM {
public int Id {get; set;}
public string Name {get; set;}
public int GroupId {get; set;}
public string GroupName {get; set;}
}
So all our db fields have prefixes so in my mapping profile I have:
RecognizePrefixes("it");
CreateMap<Item, ItemVm>();
RecognizePrefixes("gr");
CreateMap<Group, GroupVm>();
Then I Run my queries:
var items = await _dbContext.Items.ProjectTo<ItemsVM>(_mapper.ConfigurationProvider).ToListAsync();
var groups = await _dbContext.Groups.ProjectTo<GroupsVM>(_mapper.ConfigurationProvider).ToListAsync();
Then I just loop through the list of items and generate a new list of ItemsWithGroupVM and set the group name string for the final output.
How can I modify my automapper profile and ef core query to do the join and the mapping without having to loop?

Related

Asking if posible inserting primary key in related data if related data is null upon inserring

I just wandering i insert my data in relation data i tried to not insert in the related model that model. the result is null and doesnt have a key save in db.
its one-to-one relation
C# ef core
i tried this in json
{
testingName: "123231",
testingRelatedData: {
testingNameRelated: "asdasd"
}
}
and code is a normal way of adding in context.
class model {
public int modelid {get; set;}
public string testingName {get; set;}
public virtual testingNameRelated testingNameRelated { get; set; }
}
class testingNameRelated{
public int id {get; set;}
public string testingNameRelated{get; set;}
public model model {get; set;}
public int modelid {get; set;}
}
context.testing.add(model)
thanks

C#, entity framework, linq how to exclude property

public class MyObj
{
[Key]
public int id {get; set;}
public string test1 {get; set;}
public string test2 {get; set;}
public int test3 {get; set;}
public int test4 {get; set;}
public int test5 {get; set;}
public int? test6 {get; set;}
public DateTime? test7 {get; set;}
public string test8 {get; set;}
public string test9 {get; set;}
public string test10 {get; set;}
public string test11 {get; set;}
public string test12 {get; set;}
public DateTime? test13 {get; set;}
public DateTime? test14 {get; set;}
public DateTime? test15 {get; set;}
public string test16 {get; set;}
public string tes17 {get; set;}
public int test18 {get; set;}
public DateTime? test19 {get; set;}
public bool test20 {get; set;}
[ForeignKey("test3")]
public virtual Child1 child1 { get; set; }
[ForeignKey("test4")]
public virtual Child2 child2 { get; set; }
[ForeignKey("test5")]
public virtual Child3 child3 { get; set; }
[ForeignKey("test18")]
public virtual Child4 child4 { get; set; }
public virtual ICollection<Child1> child5 { get; set; }
}
var myobj = unitwork.myobjRepository.get();
I just want to pull id and test 1 to test20, without child1, child2, child3, child4 and child5.
For now, I do,
myobj.Select(x => new {
id = x.id,
test1 = x.test1
...
...
test20 = x.test20
}));
but I don't think this is right way.. Please advise me,
If the property names are the same it could be slightly simpler:
myobj.Select(x => new {
x.id,
x.test1
...
...
x.test20
}));
If you are just projecting properties with no transformation the anonymous type will use the same property names.
If you're concerned about creating an anonymous type, then you could create a named type that has only the properties you need and project to that, but there's nothing wrong with using an anonymous type from what you've shown.
What is the reason you want to do this? If you are thinking in terms of not to overload sql server, you should check lazy loading. child1, child2, child3, child4, child5 won't be loaded untill you access those properties, and you'll have MyObj class (object) available.
If you do it like you did, you endup with anonimous object. It might be ok in some scenarios but not in other.
What also might be a solution is to create another class without unnecesery field and make select into instance of that new class.
myobj.Select(x => new NewClass() {
id = x.id,
test1 = x.test1
...
...
test20 = x.test20
}));

Design models with two 'one-to-many' relationships in asp.net mvc3

I'm having a problem to design my database in ASP.NET MVC 3 using Entity Frameworks. I've followed some tutorials and tryed to adapt to my need. First time using ASP...
I have three tables: Person, Category and Example.
One Example will be in a Category that belongs to a Person, the other way around: one Person might have several Categories and each of those might have several examples.
I think I should design it with two 'one-to-many' relationships. That is my models:
public class Person
{
public int PersonID {get; set;}
public int Name {get; set;}
public string Text {get; set;}
public virtual ICollection<Category> {get; set;}
}
public class Category
{
public int CategoryID {get; set;}
public int PersonID {get; set;}
public string Name {get; set;}
public virtual ICollection<Examples> Examples {get; set;}
public virtual Person Person {get; set;}
}
public class Examples
{
public int ExamplesID {get; set;}
public int CategoryID {get; set;}
public string Title {get; set;}
public string Body {get; set;}
public virtual Category Category {get; set;}
}
I can create the Category and the Person, no problem, even using the #Html.DropDownList helper, the problem is when I try to create the Example, I wanted to populate the second dropdown with Ajax but couldn't do it and suddenly I realize there might be a flaw in my db design, In my Example model I will store the Category but not the Person, as the latter will be in already bound to the Category model, isn't it?
I'm kinda lost...
If needed I can post the Controller and/or views, but I think the problem lies in the model.
Give this a try:
public class Person
{
public int PersonID {get; set;}
public int Name {get; set;}
public string Text {get; set;}
[ForeignKey("PersonID")]
public virtual ICollection<Category> {get; set;}
}
public class Category
{
public int CategoryID {get; set;}
public int PersonID {get; set;}
public string Name {get; set;}
[ForeignKey("CategoryID")]
public virtual ICollection<Examples> Examples {get; set;}
[ForeignKey("PersonID")]
public virtual Person Person {get; set;}
}
public class Examples
{
public int ExamplesID {get; set;}
public int CategoryID {get; set;}
public string Title {get; set;}
public string Body {get; set;}
public virtual Category Category {get; set;}
}

Why am I getting circular reference error with Json serializer with a unidirectional object?

I have the following model:
public class Address
{
public int Id {get; set;}
public string Street1 {get; set;}
...
public int CountryId {get; set;}
public Country Country {get; set;}
}
public class Country
{
public int Id {get; set;}
public string Name {get; set;}
public string ISOCode {get; set;}
public string Continent {get; set;}
public string ISOCode {get; set;}
public string Languages {get; set;}
}
public class Church
{
public int Id {get; set;}
public string Name {get; set;}
public int CountryId {get; set;}
public Country Country {get; set;}
public int AddressId {get; set;}
public virtual Address Address {get; set;}
public string Phone {get; set;}
}
Does the serializer think that I have some kind of bi-directional relation going on with Country since both Church and Address have a Country object? If not, then why do I get circular reference when trying to serialize a church object?
EDIT:
What's even more confusing to me is that I'm not even including Country (on church) when I query:
var results = _context.Churches.Include(c => c.Address).Include(c => c.Address.Country).AsQueryable();
Entity Framework Context is configured so that LasyLoading is not enabled. Seems to me that Church.Country should be null and shouldn't even be an issue here.
I believe the problem lies with the fact that you're serializing EF entities, which are in fact proxies with references to DataContext. Inspect them in the debugger.
You will have to use JsonObject(MemberSerialization.OptIn) attribute and mark your properties with JsonProperty attribute. More info in documentation.

How do I create a POCO object that has 2 references to another class

I have a table (Event) that can have 2 Locations (main, alternate). Locations can be used in other tables (so no EventId in the locationTable) Using POCO self-tracking, how do I create the reference from the Event table to the Locations table, or what is the best way to handle this situation (I'm having a total brain freeze over this)? (.NET 4.0 C#, EF4.1, MVC 3 being used).
Simplified classes:
public class Event
{
public int EventId {get; set;}
public string Tile {get; set;}
public int MainLocationId {get; set;}
public int AltLocationId {get; set;}
public virtual ICollection<Location> EventLocations {get; set;}
}
public class Location
{
public int LocationId {get; set;}
public string Name {get; set;}
}
I was thinking a linking table (EventLocations) with the PK of each table and a flag indicating if it's the main or alt location, but I'm not sure how this would look in a POCO class setup. Maybe this, but it requires extra business logic (and I ultimately would like to be able to incorporate this king of solution into a T4 so I don't have to add business logic in future projects):
public class Event
{
public int EventId {get; set;}
public string Tile {get; set;}
public virtual ICollection<EventLocation> EventLocations {get; set;}
}
public class Location
{
public int LocationId {get; set;}
public string Name {get; set;}
public virtual ICollection<EventLocation> EventLocations {get; set;}
}
public class EventLocation
{
public int EventId {get;set;}
public int LocationId {get;set;}
public bool IsMain {get; set;}
public virtual Event Event {get;set;}
public virtual Location Location {get;set;}
}
Thanks for any advice/ tips/ solutions/ constructive criticism!
The simplest way is simply using:
public class Event
{
public int EventId {get; set;}
public string Tile {get; set;}
public int MainLocationId {get; set;}
public int AltLocationId {get; set;}
public virtual Location MainLocation {get; set;}
public virtual Location AlternativeLocation {get; set;}
// You can also add Foreign key properties for locations to simplify some usage scenarios
}
public class Location
{
public int LocationId {get; set;}
public string Name {get; set;}
}
You have exact number of locations defined for your event so using many-to-many relation is probably not needed (it can accidentally add more locations to your Event).

Resources