Pregunta

Si tengo tres entidades, proyectos, ProjectRole y Persona, donde una persona puede ser miembro de diferentes proyectos y estar en diferentes roles de proyecto (como "jefe de proyecto", o "Miembros del Proyecto") - la forma en que lo haría modelo tal relación?

En la base de datos, que actualmente tienen las siguientes: tablers. Proyecto y persona, ProjectRole Project_Person con PERSONID y projectId como PK y una ProjectRoleId como una relación FK

Estoy realmente en una pérdida aquí, ya que todos los modelos de dominio se me ocurren parecen romper alguna regla "DDD". ¿Hay alguna 'normas' para este problema?

Yo tenía un aspecto en un modelado de objetos aerodinámico y no hay un ejemplo lo que es un proyecto y ProjectMember se vería, pero AddProjectMember () en el Proyecto llamaría ProjectMember.AddProject (). Así Proyecto tiene una lista de ProjectMembers, y cada ProjectMember a cambio tiene una referencia al Proyecto. Parece un poco complicado para mí.

actualización

Después de leer más sobre este tema, voy a tratar lo siguiente: Hay distintas funciones, o mejor, relaciones de modelos, que son de un cierto Tipo de papel dentro de mi dominio. Por ejemplo, ProjectMember es un papel distinto que nos dice algo sobre la relación de una persona juega dentro de un proyecto. Contiene una ProjectMembershipType que nos dice más sobre el papel que desempeñará. Yo saber con certeza que las personas tendrán que jugar un papel dentro de un proyecto, así que voy a modelar esa relación.

ProjectMembershipTypes pueden ser creados y modificados. Estos pueden ser "líder del proyecto", "desarrolladores", "asesor externo", o algo diferente.

Una persona puede tener muchos papeles dentro de un proyecto, y estos roles puede comenzar y terminar en una fecha determinada. Tales relaciones son modelados por el ProjectMember clase.

public class ProjectMember : IRole
{
    public virtual int ProjectMemberId { get; set; }
    public virtual ProjectMembershipType ProjectMembershipType { get; set; }

    public virtual Person Person { get; set; }
    public virtual Project Project { get; set; }
    public virtual DateTime From { get; set; }
    public virtual DateTime Thru { get; set; }
    // etc...
}

ProjectMembershipType: es decir. "Gerente de Proyecto", "desarrolladores", "asesor"

public class ProjectMembershipType : IRoleType
{
    public virtual int ProjectMembershipTypeId { get; set; }
    public virtual string Name { get; set; }
    public virtual string Description { get; set; }

    // etc...
}
¿Fue útil?

Solución

Usted está modelando una relación de muchos a muchos:. Un proyecto puede tener muchas personas que trabajan en él, y una persona puede trabajar en varios proyectos

Usted está modelando la relación como un papel de Proyecto, que además de servir como un enlace bidireccional de persona <-> Proyecto, también registra un RoleType y empezar / final de ese relleno de la persona que RoleType en ese proyecto. (Nótese cómo el trabajo Inglés "que" hace las veces de la base de datos FK o, en el código, un puntero / referencia?)

Debido a esas FKs, podemos seguir en la base de datos del gráfico de la persona, a través del Proyecto papel, a Proyecto:

select a.person_id, b.project_role_id, c.project_id
from person a join project_role b on (a.id = b.person_id)
join project c on (b.project_id = c.id)
where a.person_id = ?

O podemos seguirlo en la otra dirección, a partir del proyecto:

select a.person_id, b.project_role_id, c.project_id
from person a join project_role b on (a.id = b.person_id)
join project c on (b.project_id = c.id)
where c.project_id = ?

Lo ideal sería que nos gustaría ser capaz de hacer lo mismo en el código C #. Así que sí, queremos que una persona tenga una lista, y el Proyecto de tener una lista y un ProjectRole referencias a una persona y un proyecto.

Sí, Project::addPerson( Person& ) realmente debe ser Project::addProjectRole( ProjectRole& ), a menos que decidimos que Project::addPerson( Person& ) es un método de conveniencia de la forma:

void Project::addPerson( Person& p ) {
  this.addProjectRole( new ProjectRole( p, &this, RoleType::UNASSIGNED ) ;
}

A ProjectRole no tiene una lista, que tiene: una referencia a una persona y una referencia a un proyecto. También tiene, como valores, una fecha de inicio, una fecha de finalización, y una RoleType (que tampoco es una enumeración, o una instancia de clase que imita un valor de enumeración - es decir, sólo hay un objeto por tipo de enumeración, y es sin estado, inmutable e idempotente, y por lo tanto puede compartir entre muchos ProjectRoles).

Ahora bien, esto no debe significar que la recuperación de una persona a partir de la base de datos debe causar toda la base de datos para ser cosificado en el gráfico de objetos en el código; proxies perezosos que sólo recuperan el uso nos pueden salvar de eso. Entonces, si sólo estamos preocupados actualmente con la persona, y no sus papeles (y Proyectos, sólo pueden recuperar la persona. (NHibernate, por ejemplo, creo que lo hace más o menos sin problemas.)

Básicamente, creo que:

1) Esta es una forma estándar de representar muchos-a-muchos relaciones; 2) Es estándar para una relación para tener datos adicionales (cuándo, qué tipo de) y; 3) usted tiene más o menos la idea correcta, y es el ser justo con razón de conciencia en conocer la opinión aquí.

Otros consejos

Así es como me gustaría manejarlo:

class Person
{
  string Name { get; set; }
  IList<Role> Roles { get; private set; }
}

class Role
{
  string Name { get; set; }
  string Description { get; set; }
  IList<Person> Members { get; private set; }
}

class Project
{
  string Name { get; set; }
  string Description { get; set; }
  IList<ProjectMember> Members { get; private set; }
}

class ProjectMember
{
  Project Project { get; private set; }
  Person Person { get; set; }
  Role Role { get; set; }
}

La ProjectMember clase trae a todos juntos. Este modelo proporciona la flexibilidad necesaria para asignar la misma persona a diferentes proyectos con diferentes roles (por ejemplo, podría ser un desarrollador de ProjectA, y un probador de ProjectB).

Por favor, no crear clases específicas de roles - esa lección se ha aprendido ya

.

He creado una muestra aplicación para demostrar esto (que incluye las relaciones también):

  1. Ejecutar " bin \ debug \ RolesRelationshipsSample.exe "
  2. Haga doble clic en los iconos de la biblioteca para crear entidades
  3. Arrastrar / soltar para asignar las relaciones apropiadas

Siéntase libre para jugar con el código. Espero que les sea útil.

¿No confundiendo la "Descripción" de un papel con el papel que una persona tiene en un proyecto? Añadir el concepto "RoleDescription" (un 'papel de clase' por así decirlo), y objetos "RoleInstance", en referencia a personas reales en proyectos puede ayudar.

Lo que tenemos es una relación de muchos a muchos con datos adicionales, el papel. Tenemos una estructura similar, excepto en nuestro caso una persona puede tener múltiples funciones en un proyecto, por lo que luché con las mismas preguntas. Una solución es crear una clase que se extiende ProjectPerson persona y agrega la propiedad papel:

public class ProjectPerson : Person
{
    public string Role { get; set; }
}

Su clase de proyecto ahora tiene una colección de ProjectPerson pero la clase Persona tiene una colección de proyecto, ya que no tiene sentido extender la clase proyecto para agregar papel. Vas a tener que hacer un trabajo adicional (consultar la Persona en la colección ProjectPerson) para encontrar el papel en un proyecto desde la perspectiva de la persona.

Una segunda solución es la manera estándar para manejar muchos-a-muchos relaciones con los datos adicionales. Crear una clase ProjectRole y modelarlo como el lado muchos de dos relaciones uno-a-muchos de proyecto y persona. Es decir, tanto del proyecto y cada persona tienen una colección de ProjectRole.

Es importante tener en cuenta qué tan bien su estrategia de acceso a los datos apoyará el modelo en la elección de una solución. ¿Quieres evitar escenarios en los que la carga de la colección requiere uno o más viajes a la base de datos para cada objeto de la colección.

Parece que hay dos entidades principales - Proyecto y el Proyecto miembros. El miembro del proyecto tiene los atributos de papel 'miembro' y 'Nombre de usuario'. Cualquiera de estos atributos pueden pertenecer a un dominio es decir, un conjunto de valores que puede mantenerse en las tablas de búsqueda tanto por conveniencia y para utilizar para la búsqueda. Se supone que alguien requiere información acerca de todos los miembros del proyecto que llevan a cabo un papel / trabajo en particular.

Nota. Las tablas de consulta pueden tener asientos secundarios pero que normalmente no tendrían el valor de una entrada cambiado. Una vez que se selecciona un valor de la tabla de consulta entonces se considera un elemento permanente de la tabla propietaria - en este caso la tabla Project miembros.

Yo no esperaría ver una entidad 'persona' o una mesa en cualquier negocio que no sea la conveniencia, como una tabla de consulta como en el caso anterior. departamentos de recursos humanos mantendrán una lista de empleados que tienen información específica que es requerida por nómina, etc, pero no hay nada fundamental cool gente que necesita la empresa para saber. NB Ubicar el proceso de negocio para identificar una entidad - no hacer las paces.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top