c# .net core 属性跟踪的几种方式

Mark:jiaguoxinzhi Linyee 属性跟踪 

首先声明,,此篇文章内容还处于研究阶段,不确保,内容正确性。。

1、Ef core方式 Microsoft.EntityFrameworkCore 3.0.0

EF core源码翻来覆去N多次,,始终没有明白具体是怎么监控属性变更的。。

大致上是,一个实体类分,跟踪映射类、原始类。

主要是通过使用 ValueComparer 来判断是否已更新

 

db.SaveChanges()时

TryDetectChanges();//状态跟踪


var entitiesSaved = DbContextDependencies.StateManager.SaveChanges(acceptAllChangesOnSuccess);//保存

 return entitiesSaved;

可见实际的保存动作是在SaveChanges(acceptAllChangesOnSuccess)

 

var entriesToSave = GetEntriesToSave();

var result = SaveChanges(entriesToSave);

    public abstract partial class InternalEntityEntry : IUpdateEntry

 SetPropertyModified SetEntityState 会增加 ChangedCount;


        /// <summary>
        ///     This is an internal API that supports the Entity Framework Core infrastructure and not subject to
        ///     the same compatibility standards as public APIs. It may be changed or removed without notice in
        ///     any release. You should only use it directly in your code with extreme caution and knowing that
        ///     doing so can result in application failures when updating to a new Entity Framework Core release.
        /// </summary>
        public virtual void DetectChanges(IStateManager stateManager)
        {
            _logger.DetectChangesStarting(stateManager.Context);

            foreach (var entry in stateManager.ToList()) // Might be too big, but usually _all_ entities are using Snapshot tracking

            {
                if (entry.EntityType.GetChangeTrackingStrategy() == ChangeTrackingStrategy.Snapshot
                    && entry.EntityState != EntityState.Detached)
                {
                    LocalDetectChanges(entry);
                }
            }

            _logger.DetectChangesCompleted(stateManager.Context);
        }

        private void LocalDetectChanges(InternalEntityEntry entry)
        {
            var entityType = entry.EntityType;

            foreach (var property in entityType.GetProperties())
            {
                if (property.GetOriginalValueIndex() >= 0
                    && !entry.IsModified(property)
                    && !entry.IsConceptualNull(property))
                {
                    var current = entry[property];
                    var original = entry.GetOriginalValue(property);

                    var comparer = property.GetValueComparer() ?? property.FindMapping()?.Comparer;

                    if (comparer == null)
                    {
                        if (!Equals(current, original))
                        {
                            LogChangeDetected(entry, property, original, current);
                            entry.SetPropertyModified(property);
                        }
                    }
                    else
                    {
                        if (!comparer.Equals(current, original))
                        {
                            LogChangeDetected(entry, property, original, current);
                            entry.SetPropertyModified(property);
                        }
                    }
                }
            }

            foreach (var property in entityType.GetProperties())
            {
                DetectKeyChange(entry, property);
            }

            if (entry.HasRelationshipSnapshot)
            {
                foreach (var navigation in entityType.GetNavigations())
                {
                    DetectNavigationChange(entry, navigation);
                }
            }
        }

由以上代码可见。。
                    var current = entry[property];
                    var original = entry.GetOriginalValue(property);
主要是通过比较以上两个值来判断是否已修改

其中 GetProperties 扫了下相关的代码,,基本上就是一个属性袋的概念,,用有序字典来保存。

 

Entity 是当前值 

_values[index] = SnapshotValue(property, value); 是快照原始值

_values 是个 ISnapshot,,是个对象 从InternalEntityEntry生成的一个动态表达式树数组

 

这里看得有点朦,,不确定是否正确

 

            return Expression.Lambda<Func<TInput, ISnapshot>>(
                    CreateConstructorExpression(entityType, parameter),
                    parameter)
                .Compile();

2 emit

emit 大约是要求实体类的属性需要带 virtual,,,否则不好用。。或许是我还没找到生成带new的方式吧。。

关键代码

            //动态创建类代理
            TypeBuilder typeBuilderProxy = moduleBuilder.DefineType($"{inType.Name}_Proxy_{inKey}", System.Reflection.TypeAttributes.Public, inType);
 

            PropertyBuilder propertyBuilder = typeBuilderProxy.DefineProperty("a", System.Reflection.PropertyAttributes.SpecialName, typeof(string), null);
            //FieldBuilder fieldBuilder = typeBuilderProxy.DefineField("_a", typeof(string), FieldAttributes.Private);
            //重写属性的Get Set方法
            var methodGet = typeBuilderProxy.DefineMethod("get_a" , GetSetMethodAttributes, typeof(string), Type.EmptyTypes);
            var methodSet = typeBuilderProxy.DefineMethod("set_a" , GetSetMethodAttributes, null, new Type[] { typeof(string) });
            var ilGetMethod = methodGet.GetILGenerator();
            ilGetMethod.Emit(OpCodes.Ret);
            //il of set method
            ILGenerator ilSetMethod = methodSet.GetILGenerator();
            ilSetMethod.Emit(OpCodes.Ret);
            //设置属性的Get Set方法
            propertyBuilder.SetGetMethod(methodGet);
            propertyBuilder.SetSetMethod(methodSet);


                //创建类实例
                var instance = Activator.CreateInstance(dict[inKey]);
                return (T)instance;

 

        private const System.Reflection.MethodAttributes GetSetMethodAttributes = System.Reflection.MethodAttributes.Public | System.Reflection.MethodAttributes.HideBySig
         | System.Reflection.MethodAttributes.NewSlot | System.Reflection.MethodAttributes.Virtual   | System.Reflection.MethodAttributes.SpecialName | System.Reflection.MethodAttributes.CheckAccessOnOverride
            ;
 

但这样写完后 发现 一直执行不到子类的方法,,一直是获取父类的方法,,不知道哪里写挂了。。还是因为3.0有bug

 

3、INotifyPropertyChanged
创建一个基类实现 INotifyPropertyChanged ,其它实体从这个基类继承。

4、Roslyc CSharpSyntaxTree

动态创建方式。。

但跟Emit一样,,强制转换为父级实体类型后,,无法监控属性变更。

 

总结:仿efCore方式才是实体ORM,属性监控的王道。其它用途则视情况选型。

仿EFcore实体ORM

主要是有个原值,缓存表。。

外面应该有个模型缓存表。

然后是上下文关联模型,关联实体,关联原值缓存表。
https://dev.tencent.com/u/jiaguoxinzhi/p/code_module/git/blob/master/LikeEfCore 此代码未成熟 不公开

 


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

灵易联盟

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值