Can we use enums as typesafe entity ids?

前端 未结 5 807
离开以前
离开以前 2021-02-05 10:21

We are working with a rather large model in a EF 6.1 code first setup and we are using ints for entity ids.

Unfortunately, this is not as typesafe as we would like, sinc

相关标签:
5条回答
  • 2021-02-05 10:43

    It's an interesting approach, but the question is: is it worth it and what are the consequences?

    You could still do something like

     if ((int)blog.BlogId == (int)comment.CommentId) { }
    

    Personally I would invest more time in educating people, writing good tests, and code reviews, instead of trying to add some form of extra complexity that influences the way you use and query your entities.

    Think - for example:

    • What effect does this casting have on performance in LINQ queries?
    • How would you enforce this if you expose your operations through Web API of WCF?
    • Does this work with navigation properties??
    • Also, you are limited in the types you could use as primary key; I don't believe this works with Guids.

    A way of additional protection is to have your domain layer handle these kinds of things by accepting entity instances instead of ID's.

    0 讨论(0)
  • 2021-02-05 10:50

    Not sure that this will work in EF but one thing you could do is to have your entities implement IEquatable<T>:

    For example your Blog class:

    public class Blog : IEquatable<Blog>
    {
        // other stuff
        public bool Equals(Blog other)
        {
            return this.Id.Equals(other.Id);
        }
    }
    

    Alternatively you could use a more flexible ORM such as NHibernate. If this is of interest, let me know and I'll expand my answer.

    0 讨论(0)
  • 2021-02-05 11:02

    I was not even familiar with this usage, but did a little digging and even the EF team says it's do-able. From their initial blog post on enum support in EF, this is listed:

    Enums as keys In addition, properties of enum types can participate in the definition of primary keys, unique constraints and foreign keys, as well as take part in concurrency control checks, and have declared default values.

    source: http://blogs.msdn.com/b/efdesign/archive/2011/06/29/enumeration-support-in-entity-framework.aspx

    I have not ever done this myself, but that quote gives me confidence. So it's possible, but as L-Three suggests: really consider if it's what you want (pros & cons .. but sounds like you have already done that) and test test test!

    0 讨论(0)
  • 2021-02-05 11:05

    I know I'm a bit late to this party, but I've used this technique and it definitely works!

    Type safety works exactly as you suggest. Compiler will catch mistakes such as

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

    And it prevents silly maths.

    currentUser.Id++;
    currentUser.Id * 3;
    

    Navigation properties still work fine too, as long as both ends of the navigation are the same enum type.

    And the SQL queries work just as they do with an int.

    It's certainly an interesting idea!

    Can you use typesafe entity IDs? - Yes!

    Should you? I'm not sure. It doesn't seem that this is how EF was designed and feels a little hacky.

    0 讨论(0)
  • 2021-02-05 11:05

    I really don't try to bash you, but how can one mix up Ids of Type X with Ids of Type Z? I never met anybody who did stuff like myBlog.Id++ either (or at least not without getting fired).

    Anyhow, here is a solution which seams to be less work and better maintainable (especiall for the db-admins):

    -In the TypeConfiguration, create an Id through the fluent API (you'll see why later)

    -Create an abstract base-class for all your entities with:

    *property: proteced int Id

    *method: public int getIdValue()

    *method: public bool isSameRecord(T otherEntity) where T: EntityBaseClass

    I guess the first method are self-explanatory, the isSameRecord will take the other instance of your base-class, does a type-check first and if it passes it, it will do a id-checkup, too.


    This is an untested approach, there's a good chance you can't create protected identifiers.

    If it doesn't work, you could create public int _id and just tell your team to not use it directly.

    0 讨论(0)
提交回复
热议问题