Default values and INotifyPropertyChanged/INotifyPropertyChanging

Discussion of open issues, suggestions and bugs regarding Entity Developer - ORM modeling and code generation tool
Post Reply
strandedpirate
Posts: 21
Joined: Tue 07 Jan 2014 12:38

Default values and INotifyPropertyChanged/INotifyPropertyChanging

Post by strandedpirate » Thu 16 Jan 2014 20:41

In the DBContext template is the below line that doesn't allow any default values if Implement INotifyPropertyChanging AND Implement INotifyPropertyChanged are both set to true.

What's the reasoning behind this logic?

I'm assuming this is simply to prevent premature firing of event notifications, but this can easily be solved with an initialization variable.

Code: Select all

if (!ImplementINotifyPropertyChanging && !ImplementINotifyPropertyChanged) {
}

Shalex
Site Admin
Posts: 9543
Joined: Thu 14 Aug 2008 12:44

Re: Default values and INotifyPropertyChanged/INotifyPropertyChanging

Post by Shalex » Mon 20 Jan 2014 15:18

If none of Implement INotifyPropertyChanging and Implement INotifyPropertyChanged is set to True, the DbContext template generates auto-implemented property and assigns a default value to the property in a class constructor:

Code: Select all

    public partial class Class1    {
        public Class1()
        {
          this.Property1 = 1111; // default value
        }
        public virtual int Property1
        {
            get;
            set;
        }
        ...
    }
If any of Implement INotifyPropertyChanging and Implement INotifyPropertyChanged is set to True, the DbContext template generates a regular property and assigns a default value to the private field in its declaration:

Code: Select all

    public partial class Class1 : INotifyPropertyChanged    {
        public Class1()
        {
        }
        public virtual int Property1
        {
            get
            {
                return _Property1;
            }
            set
            {
                if (_Property1 != value)
                {
                    _Property1 = value;
                    OnPropertyChanged("Property1");
                }
            }
        }
        private int _Property1 = 1111; // default value
        ...
    }

strandedpirate
Posts: 21
Joined: Tue 07 Jan 2014 12:38

Re: Default values and INotifyPropertyChanged/INotifyPropertyChanging

Post by strandedpirate » Wed 22 Jan 2014 07:50

Well obviously the code does have two if statements, but again, I don't see any reasoning behind why the template is written to NOT allow default values if both of those properties are set to true.

In short I needed default values and event notifications. I removed the check and added a bunch of additional bits to prevent premature firing of events. If any one is interested continue on.

You could use and set an IsInitialized variable at the end of the constructor for each entity to achieve this, which works just fine, but a much better way is to set a variable like this from your DbContext's ObjectMaterialized event. This way the notifications won't fire until the EF is finished setting the values and only changes that occur in your own code trigger notifications.

This isn't everything but the basics are as follows. At some point I'll post a new template because there is a new INotification interface I'm working on that uses lambda expressions from start to finish that should be in the BCL in the first place. string events = fail.

Template entity additions:
Every entity needs these bits.

Code: Select all

private bool _isInitialized = false;

/// <summary>
/// Returns true if the class has been initialized; false otherwise. Used to prevent premature firing of event notifications.
/// </summary>
[NotMapped]
public bool IsInitialized { get { return _isInitialized; } set { _isInitialized = value; } }
Add these extra bits to the sections dealing with firing events:

Code: Select all

if(IsInitialized)
	PropertyChanging(...);
...
if(IsInitialized)
	PropertyChanged(...);

This Initialize method would need to be fired from the constructor of the DbContext.

Code: Select all

public partial class MyDbContext
{
	partial void Initialize()
	{
		((IObjectContextAdapter)this).ObjectContext.ObjectMaterialized += ObjectContext_ObjectMaterialized;
	}

	void ObjectContext_ObjectMaterialized(object sender, System.Data.Objects.ObjectMaterializedEventArgs e)
	{
		/*
		 * set the IsInitialized property for every materialized entity to true.
		 * this allows INotification changes to fire for property changes in each entity
		 */
		var entity = e.Entity as IEntity;
		if (entity != null)
			entity.IsInitialized = true;
	}
}
IEntity is just a simple interface that so we can change the IsInitialized variable. Modify the template to have each entity implement the interface.

Code: Select all

public interface IEntity
{
	bool IsInitialized { get; set; }
}

Shalex
Site Admin
Posts: 9543
Joined: Thu 14 Aug 2008 12:44

Re: Default values and INotifyPropertyChanged/INotifyPropertyChanging

Post by Shalex » Thu 23 Jan 2014 11:13

strandedpirate wrote:I don't see any reasoning behind why the template is written to NOT allow default values if both of those properties are set to true
The default value is assigned if both Implement INotifyPropertyChanging and Implement INotifyPropertyChanged properties are set to true (checked with DbContext template):

Code: Select all

    public partial class Class1 : INotifyPropertyChanging, INotifyPropertyChanged     {
        public Class1()
        {
        }
        public virtual int Property1
        {
            get
            {
                return _Property1;
            }
            set
            {
                if (_Property1 != value)
                {
                    OnPropertyChanging("Property1");
                    _Property1 = value;
                    OnPropertyChanged("Property1");
                }
            }
        }
        private int _Property1 = 1111; // default value
        ...
    }
Please specify the exact steps we should follow to reproduce the problem with a predefined template in our environment (send us a test model if needed).

Post Reply