c# - plus - Carga lenta: ¿cuál es el mejor enfoque?
moto g4 carga lento (7)
He visto numerosos ejemplos de carga lenta: ¿cuál es tu elección?
Dada una clase modelo, por ejemplo:
public class Person
{
private IList<Child> _children;
public IList<Child> Children
{
get {
if (_children == null)
LoadChildren();
return _children;
}
}
}
La clase Persona no debería saber nada sobre cómo se cargan los niños ... ¿o debería? Seguramente debería controlar cuando las propiedades están pobladas, o no?
¿Tendría un repositorio que vincule a una Persona con su colección de niños o usaría un enfoque diferente, como usar una clase de lazyload ? Incluso entonces, no quiero que se borre una clase de lazyload en la arquitectura de mi modelo.
¿Cómo manejarías el rendimiento si primero solicitas a una Persona y luego a sus Hijos (es decir, no cargas perezosas en este caso) o de alguna manera la carga es floja?
¿Todo esto se reduce a una elección personal?
Estoy pensando que este es precisamente el tipo de problema que mejor se maneja mediante AOP (por ejemplo, PostSharp). Ten la carga floja como un aspecto y luego úsala para decorar cualquier propiedad que quieras cargar perezosamente. Descargo de responsabilidad: no lo he probado; solo pensando que debería funcionar.
La mejor carga diferida es evitarla;) La seguridad del hilo es un problema inmediato que tendrás que manejar. No tengo en cuenta la frecuencia con la que he visto que los sistemas de producción con 8 núcleos de CPU ejecutan cargas perezosas 8 veces por cada patrón de carga diferida en uso. Al menos en los inicios del servidor, todos los núcleos del servidor tienden a terminar en los mismos lugares.
Deje que un marco DI lo construya para usted, si puede. Y si no puedes, todavía prefiero la construcción explícita. Entonces, todo tipo de magia de AOP simplemente no me cortan, vaya a una construcción explícita fuera de la clase. No lo pongas dentro de la clase de persona, solo haz un servicio que construya los objetos de la manera adecuada.
La presentación de capas "mágicas" que hacen estas cosas de forma más o menos transparente parece una buena idea, pero todavía tengo que encontrarme con implementaciones que no tienen consecuencias problemáticas imprevistas.
Puede usar el patrón Virtual Proxy , junto con el patrón Observer . Esto le daría cargas perezosas sin que la clase Persona tenga conocimiento explícito sobre cómo se cargan los Niños.
Aquí hay un ejemplo que implementa la carga diferida usando el patrón Proxy
La clase Person que viviría con el resto de tus modelos. Children se marca como virtual, por lo que se puede anular dentro de la clase PersonProxy.
public class Person {
public int Id;
public virtual IList<Child> Children { get; set; }
}
La clase PersonRepository que viviría con el resto de tus repositorios. Incluí el método para incluir a los niños en esta clase, pero podrías tenerlo en una clase ChildRepository si quisieras.
public class PersonRepository {
public Person FindById(int id) {
// Notice we are creating PersonProxy and not Person
Person person = new PersonProxy();
// Set person properties based on data from the database
return person;
}
public IList<Child> GetChildrenForPerson(int personId) {
// Return your list of children from the database
}
}
La clase PersonProxy que vive con sus repositorios. Esto hereda de Person y hará la carga diferida. También podría usar un booleano para verificar si ya se ha cargado en lugar de verificar si Children == null.
public class PersonProxy : Person {
private PersonRepository _personRepository = new PersonRepository();
public override IList<Child> Children {
get {
if (base.Children == null)
base.Children = _personRepository.GetChildrenForPerson(this.Id);
return base.Children;
}
set { base.Children = value; }
}
}
Podrías usarlo así
Person person = new PersonRepository().FindById(1);
Console.WriteLine(person.Children.Count);
Por supuesto, usted puede hacer que PersonProxy tome una interfaz para el repositorio de personas y acceder a él a través de un servicio si no desea llamar directamente al repositorio de personas.
Acabo de hacer una pregunta relacionada aquí , pero fue más pesada en cuanto a Inmutability & Thread Safety tack. Muchas buenas respuestas y comentarios. Lo podrías encontrar útil.
Hablé de una solución que uso para lograr la carga lenta aquí
Puede usar la clase Lazy<T>
la que hablé aquí: ¿Cuál es la forma correcta de inyectar una dependencia de acceso a datos para la carga diferida?
También hay un enlace a una publicación de blog más detallada allí ...