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
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:
A way of additional protection is to have your domain layer handle these kinds of things by accepting entity instances instead of ID's.
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.
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!
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.
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.