0

I want to implement the GUID as the primary key in my models. I use a model-first approach, and I want the GUID to be generated not in the database, but in the .NET server.

I've seen a solution that said that I would have to do this for each class:

public class TestObject 
{
    public TestObject() 
    {
        Id = Guid.NewGuid();
    }

    public Guid Id { get; set; }
}

The problem is that: I don't think this is a clean solution, applying this to every class I have.

And I don't have the POCO classes because I am using model-first.

So, what can I do? Is this the best approach, do you think? Any advice?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
ascherman
  • 1,762
  • 2
  • 20
  • 41
  • 3
    Read Kim Tripp's [GUIDs a primary key and clustered key in SQL Server](http://www.sqlskills.com/blogs/kimberly/guids-as-primary-keys-andor-the-clustering-key/). From a DBA perspective, a GUID as your PK is a **horribly bad** choice due to massive fragmentation and thus massive negative performance repercussions. If you have the luxury of designing a new database system - **do NOT** use GUIDs as your primary keys! – marc_s Jan 14 '15 at 16:56
  • I'm not so sure it's so bad to use guid as PK: I think that there are several advantages. When I have to merge similar tables coming from different dbs (order tables in a sales force app), I don't have record from different dbs with the same PK that must be reorganized, and if I expose the PK in a web application (query string and so on) I have a little better security at 0 cost, because it's more difficult to guess other records, thing that is much more easier when you see that the PK is the typical autoincrementing integer. You can't base the security on this, but is at 0 cost. – Luca Morelli Jan 14 '15 at 17:11
  • I want to use the GUID because of what Luca is saying... I know it doesn't have a better performance, but i need to do that. Do anybody of you know how can i do what i am asking? – ascherman Jan 14 '15 at 17:17
  • If that is what you really need then you could have each class inherit from a base class that does this. And you probably want private set; And you might as well override GetHashCode and Equals to use your ID. – paparazzo Jan 14 '15 at 17:20
  • Thanks @Blam but as i am using the model first approach i don't have the POCO classes for doing what you are saying... – ascherman Jan 14 '15 at 17:22
  • OK, In summary you are hitting multiple databases and every class has it own .NET generated GUID and you are using model-first. – paparazzo Jan 14 '15 at 17:45
  • @LucaMorelli humm... and in case of interception of the request by any mean ? any body knowing the key can access to the record ? And brut force attack (or luck)?... – tschmit007 Jan 14 '15 at 17:49
  • Exactly @Blam. And as far as i know i cannot make every class inherits from some base class to generate the GUID id, so i have to create a partial class for each class i have at the model, for adding the Guid.NewGuid() at the constructor. I don't like that, it's not very clean – ascherman Jan 14 '15 at 17:51
  • 1
    @LucaMorelli And just why are you exposing the query string in a web application? Int or Guid the barn door is open. – paparazzo Jan 14 '15 at 18:00
  • I agree with @Blam. As soon as you expose that data to the end user, there is a possibility of them or someone else messing with it. Security issues surrounding primary keys are largely moot if your application has the proper security built in. The data in the database should not be responsible for application security. Furthermore, when exporting data from one database and importing it into another, you want to omit the primary keys to begin with. Primary keys are really meant to identify data within one database, not across databases. For that you need a curated "code" column. – Greg Burghardt Jan 14 '15 at 18:15

2 Answers2

0

In this case, and to answer the question independently of any other consideration, you should:

  • override the SaveChanges method
  • seek for Added entities
  • set their ID.

if your classes implement an interface such as

interface {
    Guid Id {get; set;}
}

your task will be made easier.

tschmit007
  • 7,559
  • 2
  • 35
  • 43
0

Since all of your entities seem to have Id as primary key, the most obvious thing is to modify the t4 template, so the guid initialization is generated.

In the current t4 template for entity generation (something like ModelName.tt) the constructor generation starts with...

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public <#=code.Escape(entity)#>()
    {
<#
        foreach (var edmProperty in propertiesWithDefaultValues)

(In my template it starts at line 37)

Change this into...

    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2214:DoNotCallOverridableMethodsInConstructors")]
    public <#=code.Escape(entity)#>()
    {
                this.Id = Guid.NewGuid();
<#
        foreach (var edmProperty in propertiesWithDefaultValues)
Gert Arnold
  • 105,341
  • 31
  • 202
  • 291