Duda mapping c# (.net core)

EruGreen

Hola, tengo una duda a la hora de mapear dos clases, una de ellas es una entidad de negocio y la otra es un modelo de datos ( que luego se persistirá en la bbdd), para simplificar el problema he obvado el DTO.

AuthorEntity
BookEntity
AuthorDatamodel
BookDatamodel

El problema es que si ambas entidades se referencian la una a la otra cuando mapeo los libros tengo que mapear el autor, y para ello tengo que mappear sus libros, y para ello tengo que mapear su autor, y para ello... en fin, que entra en una referencia circular, no?
Como deberia hacerlo? No quiero utilizar automapper. Gracias de antemano.

PiPePiTo

Cómo haces la query?

Yo por defecto en el select me suelo traer el primer nivel, es decir en tu caso en Author se traería sus libros pero dentro de esos libros no estaría la referencia al author cargada y lo mismo al revés.

Si estás usando Entity Framework no necesitas poner el AuthorId, cuando pones el otro modelo ya se encarga EF de hacer la relación por el ID.

Por defecto EF no va a traerse la referencia circular, si no me equivoco se va a quedar al primer nivel (o yo estoy muy acosumbrado al AsNoTracking())

Por eso pregunto que cómo haces la query.

1 respuesta
EruGreen

#2 por ahora voy a utilizar los métodos del framework, por ejemplo:
DbContext.set<T>().ToListAsync();

1 respuesta
Wei-Yu

Para la parte de base de datos no te preocupes mucho porque mientras lo modeles como te pide la docu de entity framework no tienes mucho más que rascar.

Normalmente en lo que son tus DTOs referencias otros objetos por id en vez de tener una referencia al objeto entero. Algo como:

public class BookDatamodel
{
  public Guid Id { set; get; }
  public string Name { get; set; }
  // We'd be removing this one ---
  // public AuthorDatamodel Author { get; set; }
  // -------------------------------------------
  public Guid AuthorId { get; set; }
}

Y si quieres saber algo sobre el autor, vas a buscar explícitamente el autor a través de su ID.

Si quieres exponer una relación entera pensaría cuál tiene más peso, imagino que en tu caso pesa más que si quieres encontrar información sobre el autor esta incluya ya sus libros, porque si no necesitarías hacer trabajo extra por cada libro que tenga. En cambio el autor de múltiples libros siempre sería el mismo. Esto suele ser así para todas las relaciones 1:n pero en un caso real (imagino que tu situación es para clase) hay que pensar en costes, hot paths y varias cosas extra.

p.d: hot take I guess pero haces muy bien huyendo de automapper. Nunca lo uséis.

1 respuesta
PiPePiTo

#3 Y, no te vale hacer un

.Select(s=> new Book 
{
Id = s.Id,
etc
}

Entre el Set y el ToList?

La otra opción es hacerlo después, pero estarías cargando cosas en memoria innecesariamente...

#4Wei-Yu:

p.d: hot take I guess pero haces muy bien huyendo de automapper. Nunca lo uséis.

Automapper, esa maravilla que mola... 5 minutos, hasta que te das cuenta de la que te estás liando de cara a futuro xD

1
desu

Normalmente, por defecto, no se guarda toda la información en otra tabla, solo el Id.

Busca como normalizar DB.

Author

IdName
0Foo
1Bar
2Baz

Books

IdName
0Book A
1Book B
2Book C

le añades el authorId para poder buscar

Books_b

IdNameAuthorId
0Book A0
1Book B0
2Book C1

asi que en tu diseño la lista en la tabla no es necesario, aunque ojo no tiene nada de malo si entiendes los pros/cons. dicho esto. por norma general, cada vez que quieras guardar una "lista" en un campo, seguramente es candidato a tener otra tabla. lee sobre normalización de db y te lo explicaran.

como dicen arriba, el auto mapper seguramente al ser un caso tan habitual ya sabra como meterte las cosas una dentro de otra. Si le pones que tienes una List<Libros> el automapper tiene que saber cual es el id de esos libros igualmente para hacer el fetch y guardar no? te lo hace automáticamente.

1 respuesta
pantocreitor

Por curiosidad, entityFramework te hace las mismas guarradas por detrás que JPA a la hora de mapearte los datos???
Porque te pones a mirar las operaciones y…

1 respuesta
Soltrac

Yo no uso nunca EF, me parece una puta mierda para gente que no sabe escribir un SQL de mierda. Lo del Code first, gente que no sabe ni normalizar datos en una base de datos relacional....hace llorar al niño jesús.

#7 No se lo q es JPA, pero seguro xD.

3 respuestas
Zireael

Pues yo no sabría vivir sin LINQ, salvo cosas muy específicas, no veo motivo para utilizar una stored procedure frente a linq.

1 respuesta
Soltrac

#9 Existe un intermedio entre el code first de EF y una stored procedure. Yo uso dapper por ejemplo.

1 respuesta
pantocreitor

#8 El ORM estándar de Java.

A mi parecer son de estas cosas que al principio flipas porque te facilitan la vida mucho y llega un punto que te das cuenta que montar tu las queries a manita es mucho más óptimo que dejar al ORM que haga las cosas a su rollo.

Wei-Yu

#8 Prueba las versiones nuevas y échale tiempo aprendiendo bien cómo funciona. Está muy muy bien. Lo echo muy en falta cuando toco otras cosas. Hay que saber cuándo y cómo tirar sql y entender cómo funciona la db, pero te quita muuucho trabajo de encima.

Zireael

#10 No lo conocía, le echo un ojo

1 respuesta
Roofbreaker

#6 Tal como te comentan por aquí, busca info sobre normalización de bases de datos. Hay un mundo sobre ello, pero una vez lo entiendes es "sota caballo y rey".

Podrás hacer frente a cualquier casuística relacional que se te pueda presentar al modelar.

PiPePiTo

#13 Dapper es dios xDD

Para mi es el veneno de preferencia si tengo que llamar a la DB también, tengo que decir que coincido con #8 por lo general, pero EF para cosas pequeñas te hace el papel

Dapper y DbUp para llevar las versiones de la DB xD

1 respuesta
Soltrac

#15 Me apunto lo del DbUp, es lo único que le falta a dapper, las migraciones.

De todas formas, no soy tan nazi en el fondo. Para la base de datos de mis bots uso EF. Pero mi crítica es que luego migras a un lenguaje de programación para adultos y no sabes ni escribir un SQL, normalizar las relaciones entre tablas u optimizar un query y le pasa a la gente que ha aprendido así.

Usuarios habituales

  • Soltrac
  • PiPePiTo
  • Roofbreaker
  • Zireael
  • Wei-Yu
  • pantocreitor
  • EruGreen