2009-08-11 10 views
7

En mi opinión, el campo ID de un objeto comercial debe ser de solo lectura (public get y private set) ya que por definición el ID nunca cambiará (ya que identifica de manera única un registro en la base de datos).¿El ID en el objeto comercial debe ser de solo lectura o no?

Esto crea un problema cuando crea un objeto nuevo (ID no configurado aún), guárdelo en la base de datos a través de un procedimiento almacenado que devuelve la ID recién creada y luego cómo la almacena nuevamente en el objeto si ¿La propiedad de ID es de solo lectura?

Ejemplo:

Employee employee = new Employee(); 
employee.FirstName="John"; 
employee.LastName="Smith"; 

EmployeeDAL.Save(employee); 

¿Cómo funciona el método Save (que en realidad se conecta a la base de datos para guardar el nuevo empleado) actualizar la propiedad EmployeeId en el objeto Empleado si esta propiedad es de sólo lectura (que debería ser ya que el EmployeeId nunca cambiará una vez que se haya creado).

Parece que el ID debe poder escribir en el DAL y ser de solo lectura para el resto del mundo. ¿Cómo se implementa esto especialmente si las clases DAL y Business están en ensamblajes diferentes?

No quiero crear un método Guardar en la clase Empleado ya que esta clase no debería tener nada que ver con la base de datos.

+1

Un viejo problema por el que no creo, hay una respuesta "agradable", solo un compromiso menos malo. –

+0

Anthony, borré mi respuesta. Creo que me estaba complicando demasiado. Estoy de acuerdo con @Martin Brown. No hay una respuesta simple al problema. Me gustaría crear un nuevo objeto, incluso si eso significa copiar todas las propiedades. –

+0

@ Bruno. Estaba por comentar que tu respuesta probablemente funcionaría. Parece que la mejor manera de hacerlo es hacer que la ID sea interna: public int Id {get; conjunto interno; } De esta forma, solo el DAL podrá actualizarlo y permitir que el DAL actualice la propiedad de ID 'interna': [assembly: InternalsVisibleTo ("DAL_Assembly")] De esta forma, para el DAL, la propiedad de ID interna será actualizable . – Anthony

Respuesta

2

Otra posible solución es declarar Empleado como: -

public class Employee 
{ 
    public int Id { get; internal set; } 
} 

... a condición de que las clases de los empleados y DAL están en el mismo conjunto

No pretendo que gustar, pero tengo lo usé

+0

y si no están en el mismo ensamblaje, es posible usar: [ensamblado: InternalsVisibleTo ("DAL_Assembly")] – Anthony

0

¿Qué tal:

Employee employee = new Employee(EmployeeDAL.GetNextID()); 

Esto también debe hacer que el código ahorrar más simple.

+1

o .. Empleado empleado = Empleado DAL.NewEmployee(); –

+0

Sí, prefiero la solución de Andra. – DanDan

+0

Con esta solución, el método NewEmployee() crearía un nuevo registro en la base de datos inmediatamente. El beneficio es que tendrá el EMployeed pero, ¿qué ocurre si el usuario decide no guardar al empleado al final? Debería volver a la base de datos para eliminar el registro que no parece correcto. – Anthony

1

Puede hacer que su método DAL acaba de devolver un objeto actualización:

public class EmployeeDAL 
{ 
    Employee EmployeeDAL.Save (Employee employee) 
    { 
     // Save employee 
     // Get the newly generated ID 
     // Recreate the object with the new ID and return it 
    } 
} 

Alternativamente, se puede generar una nueva identificación en el código, una instancia de un objeto con este ID a continuación, pedir a su DAL para guardarlo.

Si desea que su objeto se haya actualizado durante la operación Guardar, tendrá que hacer que esta propiedad sea pública.

Personalmente me gusta crear objetos inmutables, aquellos que solo se pueden configurar una vez pasando todos los valores al constructor. Con este enfoque, solo crearía un objeto para guardar, luego lo recuperaría junto con la ID asignada de la base de datos y se lo devolvería a la persona que llama.

+0

¿Qué pasa si el objeto tiene 50 propiedades? Debería crear un nuevo objeto, copiar el valor de todas las propiedades solo para que pueda actualizar la propiedad de ID. Funcionaría, pero no me parece correcto. Recuperar desde la base de datos funcionaría pero significa que se conecta a la base de datos dos veces: una para guardar el objeto y otra para recuperarla (cuando ya la tiene en su código de cliente). De nuevo, eso no parece correcto. – Anthony

+0

Si tiene 50 propiedades, use algo como http://www.codeplex.com/AutoMapper para asignarlas desde el objeto A al objeto B –

+0

@Anthony: Eso es cierto. Sin embargo, hay una ventaja: al recuperar de nuevo de la base de datos, obtienes exactamente lo que se guardó allí, tal vez una cadena se truncó o algo más. Si cometió un error en el código, usted en la aplicación creerá que ahora tiene este conjunto de datos, mientras que de hecho no lo hace. Pero nuevamente, estos son varios enfoques de diseño. –

1

Se podría hacer que su setter para el ID permiten establecer sólo si aún no se ha establecido antes:

public class Employee 
{ 
    private int? m_ID; 

    public int? ID 
    { 
     get { return m_ID; } 
     set 
     { 
      if (m_ID.HasValue()) 
       throw ... 
      m_ID = value; 
     } 
    } 
} 

Por otra parte, creo que algunos marcos apoyan este tipo de funcionalidad (por ejemplo, creo que NHibernate se te permite tener un setter privado en un campo de ID).

+0

Me gusta esta idea, pero solo se dará cuenta de que no puede establecer la ID si ya se ha configurado en tiempo de ejecución. Sería bueno que en tiempo de compilación la propiedad sea de solo lectura (excepto para el DAL) – Anthony

1

Cómo sobre solamente permitiendo que el código fuera de la DAL para referirse al objeto a través de una interfaz que no proporciona un setter para el campo Id (y cualquier otro campo inmutables):

public interface IEmployee 
{ 
    Int32 Id {get;} 
    String Name {get;set;} 
    // ... and so on ... 
} 

public class Employee: IEmployee 
{ 
    Int32 Id {get;set;} 
    String Name {get;set;} 
} 

El DAL puede establecer es necesario, pero el código de consumo no puede.

+0

As su clase Employee es pública (como debería ser, ya que el DAL que debería estar en un ensamble separado necesita acceder a ella), nada impide que el código consumidor cree una instancia de la clase Employee (y por lo tanto modifique la ID). – Anthony

Cuestiones relacionadas