views:

68

answers:

2

If I have a Domain Model that has an ID that maps to a SQL Server identity column, what does the POCO look like that contains that field?

Candidate 1: Allows anyone to set and get the ID. I don't think we want anyone setting the ID except the Repository, from the SQL table.

public class Thing {
    public int ID {get;set;}
}

Candidate 2: Allows someone to set the ID upon creation, but we won't know the ID until after we create the object (factory creates a blank Thing object where ID = 0 until we persist it). How would we set the ID after persisting?

public class Thing {
    public Thing () : This (ID: 0) {}
    public Thing (int ID) {
        this.ID = ID
    }
    private int _ID;
    public int ID {
        get { return this.ID;};
    }

Candidate 3: Methods to set ID?

Somehow we would need to allow the Repository to set the ID without allowing the consumer to change it. Any ideas? Is this barking up the wrong tree? Do we send the object to the Repository, save it, throw it away, then create a new object from the loaded version and return that as a new object?

+3  A: 

How about a public get accessor and an internal set accessor that throws InvalidOperationException if the underlying value is already non-zero?

Obviously you already have some way of materializing the field so that you can even load the record. Why not just use the same mechanism? After all it's not just identity values that you need to consider. It's basically any value that can change in the database after an insert/update such as computed columns, columns affected by triggers, etc.

Josh Einstein
Very good answer. That also means that the Domain Models, View Models, Repository, Factory, and any Services would exist in the same namespace (Model), which would be outside of any view or controller namespaces (MVC pattern), so they wouldn't be able to change it. If I have that correct, then this is a great answer.
Dr. Zim
+2  A: 

If you will always know the Id number when creating the class, and it will never change once the class has been created, consider using the readonly modifier, like so:

public class Thing {
    public Thing () : This (ID: 0) {}
    public Thing (int ID) {
        this._ID = ID
    }
    private readonly int _ID;
    public int ID {
        get { return this._ID;};
    }
}

This will block you at compile-time from changing the _ID field's value after it's been set by the constructor.

Warren