Breaking Change? Latest Version Makes Fields Protected

Jun 24, 2011 at 4:19 PM

I just recompiled my app, which was working with the nHydrate version prior to the latest one, and have gotten a bunch of field access errors. In all cases the field definition in the generated file now has the set accessor marked as protected. Previously they were public. For example:

		/// <summary>
		/// The property that maps back to the database 'email_recip.address' field
		/// </summary>
		/// <remarks>Field: [email_recip].[address], Field Length: 200, Not Nullable, Primary Key, Unique, Indexed</remarks>
		[EdmScalarPropertyAttribute(EntityKeyProperty = true, IsNullable = false)]
		public virtual string Address
			get { return _address; }
			protected set
				if ((value != null) && (value.Length > GetMaxLength(FieldNameConstants.Address))) throw new Exception(string.Format(GlobalValues.ERROR_DATA_TOO_BIG, value, "EmailRecipient.Address", GetMaxLength(FieldNameConstants.Address)));
				_address = value;
				_modifieddate = DateTime.UtcNow;

I'm not sure why this is happening. I didn't change anything in the schema file, so it looks to me like it's a breaking change in the latest version. If I had to guess (and it's only a guess) the fields now being given protected set accessors are components of composite primary keys. If that's true, I don't know why they have to be marked as read-only.

Again, previously this was not an issue.

- Mark

Jun 25, 2011 at 12:38 AM

I looked into the history of this problematic code fragments, and I can see where in prior versions of my codebase (which were generated by pre June 1, 2011 nHydrate) the fields in question were marked System.ComponentModel.ReadOnly(true), but the set accessor was public, not protected. Am I correct in concluding that the switch to protected was to fix a bug in how the schema got generated into code?

My problem is that I have several instances where I have master/child objects that I need to create. For example, consider Email and EmailRecipient:

id field is EmailID (database identity, int)
various other fields 
associated with EmailRecipient via EmailID -> EmailID 

id field is
EmailID (association to Email object)
Address (a string email address)

Previously what I would do is:

1) Create an instance of Email and add it to the object context via AddItem

2) Create an instance of EmailRecipient using the default/parameterless constructor

3) Assign a value to EmailRecipient.RecipientAddress

4) Assign the instance of Email to EmailRecipient.Email (which is the associated property of the relationship; sorry, that's the wrong terminology but I don't remember the right EF term offhand)

5) Add the EmailRecipient instance to the object context via AddItem.

6) Call Save() on the object context to save everything.

Since Address is no longer publicly accessible I'm going to have to add a step 1a - save instance of Email - and modify the creation of EmailRecipient to use the parametered constructor that takes an EmailID int value and a string email Address.

The additional Save (which is necessary to get an autogenerated value for Email.EmailID) will require another roundtrip to the server, which I'd prefer not to do.

So I'd really prefer the previous approach... :)

Jun 26, 2011 at 11:12 PM

I am trying to understand why this occurs as well. The property should only be protected if the table is Immutable (and cannot be changed) or the property is the primary key. Do either of these criteria apply?

Jun 27, 2011 at 4:13 AM

The properties in question are parts of primary keys. For example, EmailRecipient has a primary key composed of AssetID (an integer) and Address (a string).

FWIW, though, that key structure has been in place for quite a while, and prior to the latest release the properties in question had public set accessors, and, at least within my app, everything worked fine. In fact, as I tried to explain in my second post in this thread, the ability to set the values of the fields making up a primary key cut down on database roundtripping.

Jun 27, 2011 at 4:23 AM

Oops, I forgot to mention that none of the tables having problems are immutable.

BTW, is it possible to "downrev" an installation of nHydrate? In other words, if the 6/2/2011 release breaks my app, but the May 2011 release worked, is there a way to install the earlier version of nHydrate and have it use the earlier version of the generators?

Jun 27, 2011 at 10:09 PM

I have removed protected from primary keys. This will be in the next version. As far as rolling back this is not really feasible at this time for two reasons. First we switched from downloading generators back to a full install. Also the actual model format changed recently. So your model would not load in a much older version. In any case my change should fix your issue.

Jun 27, 2011 at 10:51 PM


Rolling back isn't necessary given that you've instituted the fix/change so quickly. I just needed the problem resolved, because it was stalling deployment of my beta.

Again, thanks for the quick response.