2

I'm changing from model first to code first with EF6 I'm using the Code first from Database option to generate my classes.

These are going to be used with a WPF application. Unfortunately the items generated do not have ObservableCollections and don't implement INotiftyPropertyChanged.

I'm wondering is there any way to automate this (by changing the behaviour of the classes c# generates when selecting the code first from DB option. Otherwise I'll have to go through and make the changes by hand which will be very tedious as we have over 100 tables.

Sample generated Class (note the properties and class don't implement INotiftyPropretyChanged and the ICollections are initialised as HashSets, when we'd like ObersvableCollections), these requirements are for data binding with WPF/XAML reasons:

{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Data.Entity.Spatial;

    [Table("TerminalSession")]
    public partial class TerminalSession
    {
        public TerminalSession()
        {
            TerminalCheckpoints = new HashSet<TerminalCheckpoint>();
            TerminalFloats = new HashSet<TerminalFloat>();
            TerminalTransactions = new HashSet<TerminalTransaction>();
        }

        public int TerminalSessionID { get; set; }

        public int? TerminalID { get; set; }

        public DateTime? StartDate { get; set; }

        public DateTime? EndDate { get; set; }

        public virtual ICollection<TerminalCheckpoint> TerminalCheckpoints { get; set; }

        public virtual ICollection<TerminalFloat> TerminalFloats { get; set; }

        public virtual ICollection<TerminalTransaction> TerminalTransactions { get; set; }
    }
}

Code we actually want:

{
    using System;
    using System.Collections.Generic;
    using System.ComponentModel.DataAnnotations;
    using System.ComponentModel.DataAnnotations.Schema;
    using System.Data.Entity.Spatial;

    [Table("TerminalSession")]
    public partial class TerminalSession : INotifyPropertyChanged
    {
        private int _terminalSessionId;
        private int? _terminalId;
        private DateTime? _startDate;
        private DateTime? _endDate;

        public TerminalSession()
        {
            TerminalCheckpoints = new ObservableCollection<TerminalCheckpoint>();
            TerminalFloats = new ObservableCollection<TerminalFloat>();
            TerminalTransactions = new ObservableCollection<TerminalTransaction>();
        }

        public int TerminalSessionID
        {
            get { return _terminalSessionId; }
            set
            {
                if (value == _terminalSessionId) return;
                _terminalSessionId = value;
                OnPropertyChanged();
                _terminalSessionId = value;
            }
        }

        public int? TerminalID
        {
            get { return _terminalId; }
            set
            {
                if (value == _terminalId) return;
                _terminalId = value;
                OnPropertyChanged();
                _terminalId = value;
            }
        }

        public DateTime? StartDate
        {
            get { return _startDate; }
            set
            {
                if (value == _startDate) return;
                _startDate = value;
                OnPropertyChanged();
                _startDate = value;
            }
        }

        public DateTime? EndDate
        {
            get { return _endDate; }
            set
            {
                if (value == _endDate) return;
                _endDate = value;
                OnPropertyChanged();
                _endDate = value;
            }
        }

        public virtual ObservableCollection<TerminalCheckpoint> TerminalCheckpoints { get; set; }

        public virtual ObservableCollection<TerminalFloat> TerminalFloats { get; set; }

        public virtual ObservableCollection<TerminalTransaction> TerminalTransactions { get; set; }
        public event PropertyChangedEventHandler PropertyChanged;

        [NotifyPropertyChangedInvocator]
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));

        }
    }
}

Option I'm selecting in visual studio. enter image description here

DermFrench
  • 3,968
  • 13
  • 43
  • 70

3 Answers3

5

Instructions are available on MSDN at Customizing Code First to an Existing Database.

Basically all you do is add the EntityFramework.CodeTemplates.CSharp NuGet package (or .VisualBasic if that's your preferred language) to your project, and it will add the T4 templates used by the wizard to the CodeTemplates\EFModelFromDatabase folder in your project.

Then you modify the T4 templates to your liking and re-run the wizard to regenerate the model from your database.

afrazier
  • 4,784
  • 2
  • 27
  • 30
  • Great answer. However, shame there was no guidance given on how to update the .t4 template. Searched high and low and can't figure this out. Figured how to edit the EntityType.t4 to change Hashset to Observable Collection, but couldn't figure how to do this for ICollection. Anyone know? – stigzler Oct 29 '18 at 21:45
0

You have the solution here: http://msdn.microsoft.com/en-us/data/jj574514.aspx

It´s in the part

"Updating code generation for data binding"

Regards

ssanga
  • 335
  • 3
  • 11
  • I think you can only do that if you use DatabaseFirst (I'm using code first and generating the code first from an existing DB). – DermFrench Dec 15 '14 at 16:33
0

I think the answer from Brian Hinchley's answer on this question works for INotiftyPropertyChanged here too (that question was similar only for an earlier version of EF, EF 4.(something).

How to get property change notifications with EF 4.x DbContext generator

If that works, I'll modify my answer with more details + instructions for how to do the observable collection part (just testing it now).

Community
  • 1
  • 1
DermFrench
  • 3,968
  • 13
  • 43
  • 70
  • You can use some of the information -- like creating a base class with common functionality for the models to inherit from -- but you're going to have to do your own template changes from scratch. They look very different in EF6 compared to the code I'm seeing for prior versions. – afrazier Dec 15 '14 at 17:01
  • @afrazier, I had it almost working, but I wasn't able to get it to generate my fields with _camelCase had to do _CamelCase for a Property named CamelCase other than that I'd everything else working. – DermFrench Dec 17 '14 at 17:26