¿Podemos usar enumeraciones como identificadores de entidad de tipo seguro?

Estamos trabajando con un modelo bastante grande en una primera configuración de código EF 6.1 y estamos usando ints para identificadores de entidad.

Desafortunadamente, esto no es tan seguro como nos gustaría, ya que uno puede mezclar fácilmente identificadores, por ejemplo, comparando identificadores de entidades de diferentes tipos (myblog.Id == somePost.Id) o similares. O peor aún: myBlog.Id ++.

Por lo tanto, se me ocurrió la idea de usar identificadores escritos, por lo que no puede mezclar identificadores. Por lo tanto, necesitamos un tipo de BlogId para nuestra entidad de blog. Ahora, la opción obvia sería usar un int envuelto en una estructura, pero no puede usar estructuras como claves. Y no puedes extender int ... - espera, ¡puedes! Usando enum!

Entonces se me ocurrió esto:

public enum BlogId : int { } 
public class Blog
{
    public Blog() { Posts = new List<Post>(); }
    public BlogId BlogId { get; set; }
    public string Name { get; set; }
    public virtual List<Post> Posts { get; set; }
}
internal class BlogConfiguration : EntityTypeConfiguration<Blog>
{
    internal BlogConfiguration()
    {
        HasKey(b => b.BlogId);
        Property(b=>b.BlogId)
           .HasDatabaseGeneratedOption(DatabaseGeneratedOption.Identity);
    }
}

Así que ahora tenemos identificadores de tipo seguro: comparar un BlogId y un PostId es un error de tiempo de compilación. Y no podemos agregar 3 a un BlogId. Las enumeraciones vacías pueden parecer un poco extrañas, pero eso es más un detalle de implementación. Y tenemos que establecer la opción DatabaseGeneratedOption.Identity explícitamente en nuestra asignación, pero eso es un esfuerzo único.

Antes de comenzar a convertir todo nuestro código a este patrón, ¿hay algún problema obvio?

Editar: Probablemente necesito aclarar por qué debemos trabajar con identificadores en lugar de entidades completas en primer lugar. A veces necesitamos hacer coincidir entidades en las consultas de EF Linq, y comparar entidades no funciona allí. Por ejemplo (basándose en el ejemplo del blog y suponiendo un modelo de dominio algo más rico): busque comentarios en las entradas de blog de los usuarios actuales. Recuerde que queremos hacerlo en la base de datos (tenemos muchos datos) y suponemos que no hay propiedades de navegación directas. Y el usuario actual no está adjunto. Un enfoque ingenuo sería

from c in ctx.Comments where c.ParentPost.Blog.Author == currentUser 

Esto no funciona, ya que no puede comparar entidades en EF Linq. Entonces tratamos

from c in ctx.Comments where c.ParentPost.Blog.Id == currentUser.Id

Esto se compila y se ejecuta pero está mal, debería haber sido

from c in ctx.Comments where c.ParentPost.Blog.Author.Id == currentUser.Id

Los identificadores de Typesafe lo habrían atrapado. Y tenemos consultas mucho más complejas que esta. Intente "buscar comentarios en las entradas de blog de los usuarios actuales hechas por otro usuario específico que el usuario actual no haya comentado más tarde".

Saludos, Niels

Respuestas a la pregunta(5)

Su respuesta a la pregunta