TrackableEntities / EntityFrameworkCore.Scaffolding.Handlebars

Scaffold EF Core models using Handlebars templates.
MIT License
210 stars 53 forks source link

[Question] How to generate an iterator for each entity graph in its own file #182

Closed omatrot closed 2 years ago

omatrot commented 2 years ago

Unless there is something already available, I'd like to generate an iterator for each entity graph by using a variation of an old t4 template. Scroll down to the The NorthwindEntityIterator Class section.

The business need is, given and old and a new entity graph, to be able to get the old and new modified properties values for tracing.

I may be wrong but it seems that this is neither a context or an entity generation process. I'm not sure wether a variation of this approach could work.

Thanks in advance.

tonysneed commented 2 years ago

Is the approach you referred to 7: Take full control by extending the Handlebars generators? https://github.com/TrackableEntities/ef-core-community-handlebars

If so, could you please provide an example of what you would like to achieve?

omatrot commented 2 years ago

I managed to use the t4 on an existing .edmx. I thought that I would need one file per entity while parsing the model. But it is only one file as shown below:

//------------------------------------------------------------------------------
// <auto-generated>
//     This code was generated from a template.
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Runtime.Serialization;

namespace RTE.Technologies.Mobile.Server.Common.DataAccessLayer.Model
{
    [DataContract(IsReference = true)]
    [KnownType(typeof(AlertDetailEntity))]
    [KnownType(typeof(AlertEntity))]
    [KnownType(typeof(AlertTrackedItemsEntity))]
    [KnownType(typeof(AvailabilityLanguageEntity))]
    [KnownType(typeof(CompanyEntity))]
    [KnownType(typeof(CompanySettingEntity))]
    [KnownType(typeof(ContextCollectionDetailEntity))]
    [KnownType(typeof(ContextCollectionEntity))]
    [KnownType(typeof(ContextDetailEntity))]
    [KnownType(typeof(ContextEntity))]
    [KnownType(typeof(ContextEnumEntity))]
    [KnownType(typeof(EnumValueEntity))]
    [KnownType(typeof(FleetDetailEntity))]
    [KnownType(typeof(FleetEntity))]
    [KnownType(typeof(GpsBoxTypeDetailEntity))]
    [KnownType(typeof(GpsBoxTypeEntity))]
    [KnownType(typeof(GpsPositionEntity))]
    [KnownType(typeof(MapConnectionEntity))]
    [KnownType(typeof(PoiEntity))]
    [KnownType(typeof(SettingDesEntity))]
    [KnownType(typeof(SettingEntity))]
    [KnownType(typeof(UnitDesEntity))]
    [KnownType(typeof(UserCalendarEntity))]
    [KnownType(typeof(UserEntity))]
    [KnownType(typeof(UserRoleEntity))]
    [KnownType(typeof(VehicleContextEntity))]
    [KnownType(typeof(VehicleEntity))]
    [KnownType(typeof(VehicleGatewayEntity))]
    [KnownType(typeof(VehicleGpsBoxInfoEntity))]
    [KnownType(typeof(VehicleSettingsEntity))]
    [KnownType(typeof(VehicleTemperatureContextEntity))]
    [KnownType(typeof(VehicleUserEntity))]
    public class CommonModelEntitiesIterator : IEnumerable<object>
    {
        [DataMember(Name = "Items")]
        protected List<object> _items;

        #region Constructors

        private CommonModelEntitiesIterator()
        {
        }

        #endregion

        #region Factory Methods

        public static CommonModelEntitiesIterator Create<T>(T entity)
        {
            CommonModelEntitiesIterator iterator = new CommonModelEntitiesIterator();
            iterator.Visit(entity);
            return iterator;
        }

        #endregion

        #region Execute Methods

        public void Execute<TFilter>(Action<TFilter> action)
        {
            foreach (var item in Items.OfType<TFilter>())
            {
                action(item);
            }
        }

        public static void Execute<TFilter>(CommonModelEntitiesIterator iterator, Action<TFilter> action)
        {
            foreach (var item in iterator.Items.OfType<TFilter>())
            {
                action(item);
            }
        }

        public static void Execute<TEntity, TFilter>(TEntity entity, Action<TFilter> action)
        {
            CommonModelEntitiesIterator iterator = CommonModelEntitiesIterator.Create(entity);
            foreach (var item in iterator.Items.OfType<TFilter>())
            {
                action(item);
            }
        }

        #endregion

        #region Properties

        public ReadOnlyCollection<object> Items
        {
            get
            {
                return WritableItems.AsReadOnly();
            }
        }

        protected List<object> WritableItems
        {
            get
            {
                if (_items == null)
                {
                    _items = new List<object>();
                }
                return _items;
            }
        }

        #endregion

        #region Visit Method

        internal void Visit(dynamic entity)
        {
            if (entity != null && !WritableItems.Contains(entity))
            {
                WritableItems.Add(entity);
                CommonModelEntitiesExtensions.Traverse(entity, this);
            }
        }

        #endregion

        #region IEnumerable Implementation

        IEnumerator<object> IEnumerable<object>.GetEnumerator()
        {
            return Items.GetEnumerator();
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
        {
            return Items.GetEnumerator();
        }

        #endregion
    }

    public static partial class CommonModelEntitiesExtensions
    {
        #region Traverse Methods

        internal static void Traverse(this AlertDetailEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this AlertEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this AlertTrackedItemsEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this AvailabilityLanguageEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this CompanyEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this CompanySettingEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this ContextCollectionDetailEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this ContextCollectionEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this ContextDetailEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this ContextEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this ContextEnumEntity entity, CommonModelEntitiesIterator visitor)
        {
            if (entity.EnumValue != null)
            {
                foreach (var value in entity.EnumValue)
                {
                    visitor.Visit(value);
                }
            }
        }

        internal static void Traverse(this EnumValueEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this FleetDetailEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this FleetEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this GpsBoxTypeDetailEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this GpsBoxTypeEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this GpsPositionEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this MapConnectionEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this PoiEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this SettingDesEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this SettingEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this UnitDesEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this UserCalendarEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this UserEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this UserRoleEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this VehicleContextEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this VehicleEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this VehicleGatewayEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this VehicleGpsBoxInfoEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this VehicleSettingsEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this VehicleTemperatureContextEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        internal static void Traverse(this VehicleUserEntity entity, CommonModelEntitiesIterator visitor)
        {
        }

        #endregion
    }

}

But the idea would be to generate a context, the entities and the iterator...

tonysneed commented 2 years ago

@omatrot I think EF Core has an API for graph traversal that you may wish to use, rather than solving the problem by generating an iterator. I suggest you post the question on the EF Core repo to see what input you get from the team.