• 读EntityFramework.DynamicFilters源码_心得_示例演示02


         上次对EntityFramework.DynamicFilters整体的项目结构有了一个认识,这次我们就通过阅读说明文档,示例项目,和单元测试,来动手构建一个我们的体验项目,通过对动态过滤器的使用,使得我们对过滤功能,在心理上有一个感性的认识,然后再一块深入学习代码内部的机理。

         首先,我们来看一下项目说明文档,项目的文档结构说明如下

      

    这是开源项目基础内容

    1. CHANGELOG: 一个修改日志,为什么会有修改日志,是对历史发布版本内容的记录,也方便其他使用者,看到修改日志,知道修改了哪些功能,对自己当前的版本有什么影响,要不要升级,等问题.下面是修改日志的内容:

    2.LICENSE:这个是做什么用的,打开看的时候,里面是什么法律责任,侵权等问题,去网上查了一下, 在开源项目创建时,还是得仔细考虑一下该用哪种License。要是以后你的项目火了,你就不会因为当初License没选对,而哑巴吃黄连——有苦说不出了。

    特别说一下,很多新手(就像我)可能根本没有为自己的项目选择License。没有为项目选择License,意味着他人不能对你的项目进行散发、改动。但他人可以以个人的名义使或以商业用途使用你的软件。另外,如果你将没有License的项目传到了Github上,你就默认接受了Github的服务条款协议——别的用户可以查看或者fork你的项目。

    这个网站介绍了各种license的区别:https://choosealicense.com/licenses/

    3.Readme.md:第一次打开这个文档是下面这个样子的

    去网上找了一下,那么md后缀的文件到底是个什么鬼呢,看这里:

    http://www.kuqin.com/shuoit/20141125/343459.html

    怎么打开呢,我在vs2015扩展里面,安装了一个插件:

    再打开文档的时候,就是这个样子:

    左边可以编辑,右边马上就显示了编辑的效果,确实不错

    README 应该是介绍code source 的一个概览.其实这个静态文件是有约定成俗的规范.

    1.项目介绍

    2.代码实现了什么功能?

    3.该如何使用? (系统环境参数,部署要素)

    4.代码组织架构是什么样的?

    5.版本更新重要摘要

    如果你的README包括上面的内容,那么当使用者拿到代码,打开README后,基本就知道该如何下手了

    下面是创建的体验项目:

    第一步:新建控制台应用程序

    第二步:通过nuget包管理器,引用:

                   1.EntityFramework 6.1.2

             2.EntityFramework.DynamicFilters.2.6.0

    第三步:添加dbContext,model

    添加DemoContext:

     public class DemoContext: DbContext
        {
            public static Guid CurrentAccountID { get; set; }
            public DbSet<Account> Accounts { get; set; }
            public DbSet<BlogEntry> BlogEntries { get; set; }
    
            public DemoContext()
            {
                Database.SetInitializer(new ContentInitializer<DemoContext>());
                Database.Log = log => System.Diagnostics.Debug.WriteLine(log);
                Database.Initialize(false);
            }
    
            protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                base.OnModelCreating(modelBuilder);
            }
        }
    
        public class ContentInitializer<T> : DropCreateDatabaseAlways<T>
           where T : DemoContext
        {
            protected override void Seed(T context)
            {
                System.Diagnostics.Debug.Print("Seeding db");
    
                //  Seeds 2 accounts with 9 blog entries, 4 of which are deleted
    
                var homer = new Account
                {
                    UserName = "homer",
                    BlogEntries = new List<BlogEntry>
                    {
                        new BlogEntry { Body="Homer's first blog entry", IsDeleted=false, IsActive=true, StringValue="1"},
                        new BlogEntry { Body="Homer's second blog entry", IsDeleted=false, IsActive=true, StringValue="2"},
                        new BlogEntry { Body="Homer's third blog entry (deleted)", IsDeleted=true, IsActive=true, StringValue="3"},
                        new BlogEntry { Body="Homer's fourth blog entry (deleted)", IsDeleted=true, IsActive=true, StringValue="4"},
                        new BlogEntry { Body="Homer's 5th blog entry (inactive)", IsDeleted=false, IsActive=false, StringValue="5"},
                        new BlogEntry { Body="Homer's 6th blog entry (deleted and inactive)", IsDeleted=true, IsActive=false, StringValue="6"},
                    }
                };
                context.Accounts.Add(homer);
    
                var bart = new Account
                {
                    UserName = "bart",
                    BlogEntries = new List<BlogEntry>
                    {
                        new BlogEntry { Body="Bart's first blog entry", IsDeleted=false, IsActive=true, StringValue="7"},
                        new BlogEntry { Body="Bart's second blog entry", IsDeleted=false, IsActive=true, StringValue="8"},
                        new BlogEntry { Body="Bart's third blog entry", IsDeleted=false, IsActive=true, StringValue="9"},
                        new BlogEntry { Body="Bart's fourth blog entry (deleted)", IsDeleted=true, IsActive=true, StringValue="10"},
                        new BlogEntry { Body="Bart's fifth blog entry (deleted)", IsDeleted=true, IsActive=true, StringValue="11"},
                        new BlogEntry { Body="Bart's 6th blog entry (inactive)", IsDeleted=false, IsActive=false, StringValue="12"},
                        new BlogEntry { Body="Bart's 7th blog entry (deleted and inactive)", IsDeleted=true, IsActive=false, StringValue="13"},
                    }
                };
                context.Accounts.Add(bart);
    
                context.SaveChanges();
            }
        }

    添加两个实体:

     public class BlogEntry : ISoftDelete
        {
            [Key]
            [Required]
            [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
            public Guid ID { get; set; }
    
            public Account Account { get; set; }
            public Guid AccountID { get; set; }
    
            public string Body { get; set; }
    
            public bool IsDeleted { get; set; }
    
            public int? IntValue { get; set; }
    
            public string StringValue { get; set; }
            public DateTime? DateValue { get; set; }
    
            public bool IsActive { get; set; }
        }
    
        public interface ISoftDelete
        {
            bool IsDeleted { get; set; }
        }
    
        public class Account
        {
            [Key]
            [Required]
            [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
            public Guid ID { get; set; }
    
            public string UserName { get; set; }
    
            public ICollection<BlogEntry> BlogEntries { get; set; }
    
            /// <summary>
            /// Column used to verify handling of Entity properties mapped to different conceptual property names.
            /// </summary>
            [Column("RemappedDBProp")]
            public bool RemappedEntityProp { get; set; }
        }

    第四步:重写dbcontext里面 protected override void OnModelCreating(DbModelBuilder modelBuilder) 构建动态过渡器

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
            {
                base.OnModelCreating(modelBuilder);
                modelBuilder.Filter("BlogEntryFilter", (BlogEntry b, Guid accountID, bool isDeleted) => (b.AccountID == accountID) && (b.IsDeleted == isDeleted),
                                                    () => CurrentAccountID, () => false);
            }

    构造了一个过滤器,自动添加条件,查询数据没有被软件删除,且只属于当前登录用户的数据。

    调用

    var demoContext = new demo.DemoContext();
                var allBlogEntries = demoContext.BlogEntries.ToList();
                foreach (BlogEntry blogEntry in allBlogEntries)
                {
                    Console.WriteLine(blogEntry.Body);
                }

    通过阅读:开源项目里面的reademe.md文档,简单的把这个动态过滤器,用到ef实体的自动查询上。

    公司用的rafy,当时只是知道怎么用rafy的过滤条件,现在想想应该也跟这种方式差不多,像rafy的幽灵插件,只是rafy想根据条件,配置动态查询条件是否方便,之前都只是单独添加插件,确实没有考虑动态的问题,现在ef的这个动态过滤从全局控制确实挺方便的。

  • 相关阅读:
    关于lucene断点续索引和增量索引的问题
    发布一个关于统计时间段的MDX语句
    【蛙蛙推荐】想设计一个关于软件开发的元搜索引擎,希望大家支持
    python中and和or的用法
    Hadoop实战中高级部分 之 Hadoop MapReduce高级编程
    (转)对实时分析与离线分析的思考(二)
    数据分析站点导航
    MapReduce:详解Shuffle过程
    分析能力的8个等级(My Level)
    (转)Tire Tree
  • 原文地址:https://www.cnblogs.com/gdnyfcuso/p/6528776.html
Copyright © 2020-2023  润新知