2010-09-21 16 views
11

¿Cuál es el mejor enfoque para implementar un CRUD en la interfaz de uso de BL que se utilizará para abstraer las operaciones DAL? Necesito sus chicos de opinión ..Implementación de un CRUD utilizando una interfaz

Aquí es mi proyecto ..

entidades de datos que se asignan en la tabla de base de datos

public class Student 
{ 
    public string StudentId { get; set; } 
    public string StudentName { get; set; } 
    public Course StudentCourse { get; set; } 
} 

public class Course 
{ 
    public string CourseCode { get; set; } 
    public string CourseDesc { get; set; } 
} 

creé una interfaz CRUD para las operaciones del objeto abstracto

public interface IMaintanable<T> 
{ 
    void Create(T obj); 
    T Retrieve(string key); 
    void Update(string key); 
    void Delete(string key); 
} 

Y luego un componente que gestiona la entidad y sus operaciones implementando la interfaz

public class StudentManager : IMaintainable<Student> 
{ 
    public void Create(Student obj) 
    { 
     // inserts record in the DB via DAL 
    } 

    public Student Retrieve(string userId) 
    { 
     // retrieveds record from the DB via DAL 
    } 

    public void Update() 
    { 
     // should update the record in the DB 
    } 

    public void Delete(string userId) 
    { 
     // deletes record from the DB 
    } 
} 

ejemplos de uso

public void Button_SaveStudent(Event args, object sender) 
    { 
     Student student = new Student() 
     { 
      StudentId = "1", StudentName = "Cnillincy" 
     } 

     new StudentManager().Create(student); 
    } 

como se puede ver, no es un gran anomalías en el método de actualización

public void Update() 
    { 
     // should update the record in the DB 
    } 

lo que debe tener este método para actualizar la propiedad objetos? ¿Debo heredar el Student?

public class StudentManager : Student , IMaintainable<Student> 
    { 
     public void Update() 
     { 
      //update record via DAL 
     } 
    } 


    public void Button_SaveStudent(Event args, object sender) 
    { 
     Student student = new StudentManager(); 
     student.StudentId = "1"; 
     student.StudentName = "Cnillincy" 
     student.Update() 
    } 

¿O debería contener la clase de Estudiante como un atributo del administrador de estudiantes?

 public class StudentManager : IMaintainable<Student> 
    { 
     public Student student { get; private set }; 

     public void Create() {} 
     public void Update() {} 
     public void Retrieve() {} 
     public void Delete() {} 
    } 

¿Qué más apropiado? ¿Qué pasa con la interfaz? Alguna otra sugerencia chicos? thanks..C

Respuesta

14

Su interfaz CRUD probablemente debe ser similar

public interface IMaintanable<T> 
{ 
    string Create(T obj); 
    T Retrieve(string key); 
    void Update(T obj); 
    void Delete(string key); 
} 

que es, tanto Create y Update tomar una copia del objeto que se está actualizando. La diferencia es que el Update puede obtener el key del obj, por lo que sabe qué objeto está cambiando. Create normalmente haría que se creara la clave, por lo que la devolvería como valor de retorno. Espero que ayude.

(La actualización también podría pasar de nuevo la clave también.)

+0

cree que es más eficiente que heredar el objeto, porque significa que creará otra copia del obj en lugar de simplemente actualizarlo ,, – CSharpNoob

+2

Heredar no tendría sentido. Su StudentManager NO ES un estudiante. – Matthieu

+0

Lo que dijo Matthieu. Piense en el alumno como un registro y su StudentManager como la secretaria del director, escribiendo los registros a medida que aparecen. Principio de responsabilidad única FTW. – Lunivore

0

yo no haría StudentManager heredan estudiante, me gustaría hacer mi método de actualización de estado como lo es su método de crear, es decir

public interface IMaintanable<T> 
{ 
    void Create(T obj); 
    T Retrieve(string key); 
    void Update(T obj); 
    void Delete(string key); 
} 

y

public void Update(T obj) 
{ 
    // should update the record in the DB 
} 
+2

¿podría explicar por qué esto es más apropiado que heredar o atribuir DataEntity? gracias – CSharpNoob

+1

Para mí se trata de OO "corrección" y la separación de las preocupaciones; Un StudentManager no es un Estudiante (en un sentido OO). La responsabilidad de las clases de los estudiantes es modelar los datos, la responsabilidad de StudentManagers es persistir en los datos, solo creo que esos no deben ser mixtos. Pero eso es sólo mi opinión, puede que no tenga razón :) – JonoW

2

Lo vi de Rob Conery que realmente me gusta. Su poder radica en la flexibilidad de los argumentos que puede pasar a los métodos. Su implementación no es lo suficientemente robusta como IMO. Consulte su kit de inicio de MVC aquí http://mvcstarter.codeplex.com/ (se llama ISession allí).

public interface IMaintainable : IDisposable 
    { 
     T Single<T>(Expression<Func<T, bool>> expression) where T : class, new(); 
     System.Linq.IQueryable<T> All<T>() where T : class, new(); 
     void Add<T>(T item) where T : class, new(); 
     void Update<T>(T item) where T : class, new(); 
     void Delete<T>(T item) where T : class, new(); 
     void Delete<T>(Expression<Func<T, bool>> expression) where T : class, new(); 
     void DeleteAll<T>() where T : class, IEntity, new(); 
     void CommitChanges(); 
    } 
+0

esto es como IEnumerable métodos de extensión ... gracias – CSharpNoob

+0

No hay problema ... Una vez que eche un vistazo a su solución, verá qué pequeño código realmente necesita hacer la mayoría de las operaciones CRUD. –

+0

@JamesSouth recibe un error en la palabra clave IEntity –

9

Personalmente, creo que lo único que falta es la terminología adecuada. Lo que esto realmente es una aproximación de un patrón muy útil, llamado patrón de repositorio.En cuanto a type-awareness, goes, la implementación se denominaría repositorio genérico.

La forma en que he implementado personalmente en el pasado era tener una interfaz que definiera el repositorio, como IRepository<T>, y una clase base que sea específica para el tipo de repositorio, como SqlRepositoryBase<T>. La razón por la que haría esto es porque puedo poner el código específico de la implementación en la clase base. Entonces, la plomería está lista y puedo preocuparme por la implementación específica del dominio en el repositorio final, que sería StudentRepository, SqlRepository<Student> (o SqlRepository<IStudent> si define interfaces para su entidad).

Parece que le preocupa la cantidad de objetos que están instalados, y le puedo decir que no está generando una fuga de recursos suficientemente significativa como para realmente preocuparse por la implementación de esta manera. Los veteranos pueden avergonzarse por el hecho, pero ya no estamos tratando de optimizar 64k o RAM. ;-) Se trata más de mantenimiento, contratos de código, etc.

No se debe agregar complejidad innecesaria por adelantado, pero también es posible que desee examinar el Patrón de unidad de trabajo si está buscando alistar múltiples entidades de diferente tipos en transacciones atómicas.

Aquí hay un par de buenas referencias para estos temas:

Dos comida para llevar de este en general (en mi humilde opinión):

  • I personalmente no estoy de acuerdo con la suposición de que un repositorio patt Este enfoque solo tiene utilidad en proyectos más grandes; especialmente el patrón de repositorio genérico. Si comienza a poner código como este en una biblioteca reutilizable, se sorprenderá de lo rápido que puede comenzar a crear un recurso invaluable de bloques de construcción.

  • La mayor ventaja de este enfoque es la gran capacidad de prueba de la misma; incluso más que la reutilización. Si está buscando burlarse de sus repositorios para cualquier tipo de aproximación TDD, puede hacerlo con poco esfuerzo. Esto le permitirá escribir pruebas más completas sobre los usos de los repositorios a lo largo de su código.

+1

Un patrón CRUD como este es básicamente un patrón de repositorio de todos modos, como quiera que lo llame. Estoy de acuerdo con su comentario acerca de que es útil incluso para proyectos pequeños. Lo bueno de abordarlo desde un punto de vista CRUD es que se traduce muy bien en REST. REST, incluso mal hecho, es bastante eficiente y escalable. Con un dominio como los estudiantes, a los que se accede en gran medida solo unos pocos días cada año, el rendimiento podría ser una consideración, incluso si no es un factor diferenciador. – Lunivore

+0

Joseph, años más tarde todavía valioso, como tal el enlace para "La unidad del patrón de trabajo" está roto, ¿puedes actualizar esto? – Edward

+0

@Edward - hecho. Usó la Máquina de Wayback para extraer un archivo de ella. ¡Gracias! –

0

Eche un vistazo a la nueva Entity Framework 4 que se lanzó recientemente. Están presentando un modelo de "código por convención" que le permite mapear fácilmente sus objetos comerciales directamente en la base de datos sin tener que preocuparse por un DAL.

"The Gu" tiene un great series que describe lo fácil que es asignar sus objetos, e incluso hacer algunas modificaciones simples cuando se vincula a la base de datos a través del modelo DbContext que utiliza.

Vale la pena señalar que la versión actual está en CTP4, pero anticipo que la mayoría de los problemas ya se han resuelto con el marco y deberían servirle bien.

0

Me cambiaron las respuestas aquí un poco, a esto:

public interface IMaintanable<T> 
{ 
    Guid Create(T obj); 
    T Read(Guid key); 
    bool Update(T obj); 
    bool Delete(Guid key); 
} 

Esta interfaz se basa en mi estructura de base de datos. Yo uso Guids para claves primarias.

+1

Podría ser bueno explicar por qué sugiere el cambio ... –

Cuestiones relacionadas