Object framework advanced application: Dynamic Filtering of EntityFramework DynamicFilters and entityframework

Source: Internet
Author: User

Object framework advanced application: Dynamic Filtering of EntityFramework DynamicFilters and entityframework
Object framework advanced application-Dynamic Filtering EntityFramework DynamicFilters

Let's go straight to the theme.

 

1. What is EntityFramework DynamicFilters and what can it do?

EntityFramework DynamicFilters is an open-source project. You can download its source code here. As the name suggests, what it does for us is to help us dynamically filter data. To take care of beginners, let's start from scratch.

1. What is data filtering?

Data filtering is simple, that is, removing unwanted data. The where clause in SQL statements, the where clause in Linq, And the extension method Where are used to complete this glorious task.

 

2. What is dynamic?

Dynamic means that the conditions we write are not rigidly applied. For example, if we write a where clause in one place, it can only be used for this query. The next time we encounter a similar situation, we have to honestly write where xxx = xxx. For a long time, we have been using this method in harmony. Suddenly one day, I captured my head: in similar cases, how good would it be if I could automatically add the appropriate considerations or apply the corresponding rules? So there is dynamic. Of course, the dynamics here are just one aspect of the problem.

 

3. What can it do for a long time? What is the specific point?

It can create a global filter for the object framework query. These filters are automatically applied to each query.Can be used to support multi-tenant and soft DeletionAnd so on. The filter can be created by returning a Boolean-type Linq expression, and the Contains () operator (method) is also supported ). Currently, the supported databases include ms SQL Server (including Azure), MySql, and Oracle.

 

2. How do we do it without it?

Let's take soft deletion (instead of deleting data in the true sense, we just make a deletion ID on the corresponding record) as an example. Because the data is not actually deleted, but marked by an identifier, we have to add a condition (filter out the data marked as deleted) to each query. The Code may grow like this:

1  var blogs = context.BlogEntries.Where(b => b.IsDeleted == false).ToList();

The above Code does not need to be explained. I believe you can understand it. If it is an SQL statement, you may say that it is difficult. I am looking for a place to splice all the queries and this condition is not OK. This is true, but here we only use this simple scenario as an example. What about complicated scenarios? Secondly, the join condition of the Linq expression is not as casual as the string, but at least a large part of people are like this, and of course it also contains me. This condition is manually added for each query. It not only increases the workload, but also reduces the maintainability and disperses the attention of our core business logic.

 

Iii. EntityFramework DynamicFilters changes

Of course,It is only one of the many solutions, but the author has not made it a treasure for his own computer.I only need to add a filter in the OnModelCreating METHOD OF THE CONTEXT DbContext. The Code is as follows:

1 protected override void OnModelCreating (DbModelBuilder modelBuilder) 2 {3 base. onModelCreating (modelBuilder); 4 5 // restrict all considerations for BlogEntry queries (only those that have not been deleted are obtained) 6 // The Global overhead here is used with delegation, so that the value 7 needs to be calculated every time. // if the value uses a delegate, make sure that it is global in your application, 8 modelBuilder. filter ("BlogEntryFilter", (BlogEntry B, bool isDeleted) => (B. isDeleted = isDeleted), 9 () => false); 10 11}

In this way, it adds a condition (B => B. IsDeleted = false) to each of our queries about the Blog entity ). We don't have to worry about how to add this condition. The usage is completely transparent, just like without it. The sample code is as follows:

1 /// <summary> 2 /// query 3 /// </summary> 4 /// <param name = "context"> </param> 5 /// <param name = "userName"> </param> 6 private static void Query (ExampleContext context, string userName) 7 {8 var account = context. accounts 9. include (a =>. blogEntries ). firstOrDefault (a =>. userName = userName );
13 Console. writeLine ("account {0} blogs are:", userName); 14 if (account = null) return; 15 foreach (var blog in account. blogEntries) 16 {17 Console. writeLine ("{0}", blog. id); 18} 19}

However, in the same context DbContext instance, if the browser is disabled before the browser is used, and the data is cached, the filter will not take any effect, when using the filter, you must avoid the impact of changing the filter in the same context.

If you do not want to use the timer in some cases, you can disable it using the following code:

1 // disable filter 2 context. DisableFilter ("BlogEntryFilter ");

 

Note: disabling is only valid for the current context DbContext instance and does not affect other context instances. If you want to be valid for all context instances, you can use the global disabling function in the OnModelCreating method:

1 // global filter disabled 2 modelBuilder. DisableFilterGlobally ("BlogEntryFilter ");

 

The code that is enabled is similar, so there is not much here. Check the Code directly:

1 // enable the filter 2 context. EnableFilter ("BlogEntryFilter"); 3 context. EnableAllFilters ();

 

Let's take a look at the effect of using a filter. The Code is as follows:

1 class Program {2 static void Main (string [] args) {3 4 // by default, the filter enables 5 var context = new ExampleContext (); 6 7 Console. writeLine ("Query using the filter BlogEntryFilter"); 8 Query (context, "homer"); 9 10 // disable the filter 11 context. disableFilter ("BlogEntryFilter"); 12 13 Console. writeLine ("Disable the filter BlogEntryFilter for Query"); 14 Query (context, "homer"); 15 16 Console. readLine (); 17} 18 19 /// <summary> 20 // query 21 /// </summary> 22 /// <param name = "context"> </param> 23 /// <param name = "userName"> </param> 24 private static void Query (ExampleContext context, string userName) 25 {26 var account = context. accounts27. include (a =>. blogEntries ). firstOrDefault (a =>. userName = userName); 28 29 Console. writeLine ("account {0} blogs are:", userName); 30 if (account = null) return; 31 foreach (var blog in account. blogEntries) 32 {33 Console. writeLine ("{0}", blog. id); 34} 35} 36}

 

The code output is as follows:

 

Iv. Principles of EntityFramework DynamicFilters

It is implemented by adding the extension method Filter on the object DbModelBuilder. The core code is as follows:

 1   private static void Filter<TEntity>(DbModelBuilder modelBuilder, string filterName, LambdaExpression predicate, params object[] valueList) 2         { 3             InitializeDynamicFilters(null); 4  5             filterName = ScrubFilterName(filterName); 6  7             modelBuilder.Conventions.Add(new DynamicFilterConvention(filterName, typeof(TEntity), predicate)); 8  9             //  Always add the filter to _GlobalParameterValues - need it to be able to disable it10             _GlobalParameterValues.TryAdd(filterName, new DynamicFilterParameters());11 12             int numParams = predicate.Parameters == null ? 0 : predicate.Parameters.Count;13             int numValues = valueList == null ? 0 : valueList.Length;14             for (int i = 1; i < numParams; i++)15             {16                 object value = ((i - 1) < numValues) ? valueList[i - 1] : null;17                 SetFilterGlobalParameterValue(null, filterName, predicate.Parameters[i].Name, value);18             }19         }

 

The source code of the entire project is not much. If you are interested, please read the source code. The code used in this article should be downloaded at the end.

Finally, I want to explain that I have not completed all aspects of EntityFramework DynamicFilters, But I just talked about some common scenarios. For more details, read the source code or practice and communicate with everyone.

 

Sample source code: http://files.cnblogs.com/files/VolcanoCloud/EFDynamicFilterDemo.rar

 

Entity Framework exchange QQ group: 458326058. You are welcome to join us.

Thank you for your continued attention, my blog address: http://www.cnblogs.com/VolcanoCloud/

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.