Entity Framework object Framework formation tour-several typical operations on the interface (8), entityframework
In the previous article, "The Journey of Entity Framework formation -- separation and combination of data transmission model DTO and Entity model Entity, this article introduces DTO objects in the Entity Framework object Framework. The separation and Union of the data transmission model DTO and the Entity model Entity well isolates their relationships, so that even the complex Entity model Entity does not affect the data transmission and processing of the WCF interface. This article describes how to implement a variety of common processing operations on the Interface Based on this separation model.
1. Regular business addition and update operations
As we introduce DTO objects to increase business objects, DTO objects must be used in the processing end of the interface. The following Code adds and modifies the processing operations.
public bool SaveAddNew() { DictDataInfo info = new DictDataInfo(); SetInfo(info); try { bool succeed = CallerFactory<IDictDataService>.Instance.Insert(info); if (succeed) { int intSeq = 0; string seqValue = this.txtSeq.Text; if (int.TryParse(seqValue, out intSeq)) { this.txtSeq.Text = (intSeq + 1).ToString().PadLeft(seqValue.Trim().Length, '0'); } this.txtName.Focus(); this.txtName.SelectAll(); } return succeed; } catch (Exception ex) { LogTextHelper.Error(ex); MessageDxUtil.ShowError(ex.Message); } return false; } public override bool SaveUpdated() { DictDataInfo info = CallerFactory<IDictDataService>.Instance.FindByID(ID); if (info != null) { SetInfo(info); try { bool succeed = CallerFactory<IDictDataService>.Instance.Update(info, info.ID.ToString()); return succeed; } catch (Exception ex) { LogTextHelper.Error(ex); MessageDxUtil.ShowError(ex.Message); } } return false; }
The above operations are similar to the code used by my previous hybrid framework. The original framework is based on the EnterpriseLibrary architecture. The entity class adopts the "table name + Info" method, although the ** Info here represents the DTO object and is the ing Class of the Entity object of the object framework, the processing code in the overall business is almost the same, this is also one of the changes that I want to see more smooth transitions and easy to understand.
2. DTO expression-Based Query Processing
For queries, we know that conditional expressions of strings can also be used for processing operations. However, the SQL statements must be hard-coded to ensure high security, it may not be good. Since the Entity Framework can use Lamda expressions for queries, can we also use Lamda expressions on the interface to replace conditional SQL statements?
As we know, the previous article has introduced the introduction of DTO objects to decouple the object model of the object framework, as shown in the following module hierarchy scenario.
In this way, we can still use the Expression <Func <T, bool> of the Entity Framework when designing the BLL business logic layer, for example, the interface definition at the IBLL layer uses the following interface for Expression expressions.
/// <Summary> /// query the database based on the condition, returns the object set /// </summary> /// <param name = "match"> conditional expression </param> /// <returns> </returns> IList <t> Find (Expression <Func <T, bool> match ); /// <summary> /// return the record source that can be queried Based on the condition expression // </summary> /// <param name = "match"> query condition </ param> /// <param name = "sortPropertyName"> sort attribute name </param> // <param name = "isDescending"> if it is true, it is in descending order, otherwise, it is in ascending order </param> /// <returns> </returns> IQueryable <T> GetQueryable (Expression <Func <T, bool> match, string sortPropertyName, bool isDescending = true );
However, this Expression <Func <T, bool> cannot be used in the Facade layer, and the IQueryable <T> interface cannot be used in the Facade layer, because the WCF Service Cannot serialize this interface.
For this reason, how should we pass the Expression <Func <T, bool> match Expression of the condition parameter? The answer is to introduce Serialize. the Linq component uses the ExpressionNode object for bearing, and finally resolves it as Expression <Func <T, bool> match for processing.
/// <Summary> /// query the database based on the condition, returns the object set /// </summary> /// <param name = "match"> conditional expression </param> /// <returns> </returns> [OperationContract (Name = "Find")] IList <DTO> Find (ExpressionNode match); // <summary> // query the database based on conditions and return the object set (asynchronous) /// </summary> /// <param name = "match"> condition expression </param> /// <returns> </returns> [OperationContract (Name =" findAsync ")] task <IList <DTO> FindAsync (ExpressionNode match );
We need to construct an ExpressionNode object for processing in the client interface. The Query Processing code is as follows.
Here, we need to first process Expression <Function <T, boo> to ExpressionNode by calling expression. ToExpressionNode ();, as shown in the following code.
Private ExpressionNode GetCondtionSql () {Expression <Func <DictDataInfo, bool> expression = p => p. dictType_ID = this. lblDictType. tag. toString (); var queryNode = expression. toExpressionNode (); return queryNode;} private void BindData () {# region add alias resolution this. winGridViewPager1.DisplayColumns = "Name, Value, Seq, Remark, EditTime"; this. winGridViewPager1.AddColumnAlias ("ID", "No."); this. winGridViewPager 1. addColumnAlias ("DictType_ID", "dictionary category"); this. winGridViewPager1.AddColumnAlias ("Name", "Project Name"); this. winGridViewPager1.AddColumnAlias ("Value", "project Value"); this. winGridViewPager1.AddColumnAlias ("Seq", "dictionary sorting"); this. winGridViewPager1.AddColumnAlias ("Remark", "Remarks"); this. winGridViewPager1.AddColumnAlias ("Editor", "Modify user"); this. winGridViewPager1.AddColumnAlias ("EditTime", "update date"); # endregion if (this. lblD IctType. Tag! = Null) {ExpressionNode condition = GetCondtionSql (); WHC. pager. entity. pagerInfo pagerInfo = this. winGridViewPager1.PagerInfo; IList <DictDataInfo> list = CallerFactory <IDictDataService>. instance. findWithPager (condition, ref pagerInfo); // this. winGridViewPager1.PagerInfo. recordCount = pagerInfo. recordCount; this. winGridViewPager1.DataSource = new WHC. pager. winControl. sortableBindingList <DictDataInfo> (list );}}
On the implementation side of the Facade interface, we need to turn the ExpressionNode into an Expression <Function <T, boo> object.
/// <Summary> /// query the database based on the condition, returns the object set /// </summary> /// <param name = "match"> conditional expression </param> /// <returns> </returns> public virtual IList <DTO> Find (ExpressionNode match) {Expression <Func <Entity, bool> mappedSelector = ConvertExpression (match); IList <Entity> tList = baseBLL. find (mappedSelector); return tList. mapToList <Entity, DTO> () ;}/// <summary> // query the database based on conditions and return the object set (asynchronous) /// </summary> /// <param name = "match"> condition expression </param> /// <returns> </returns> public virtual async Task <IList <DTO> FindAsync (ExpressionNode match) {Expression <Func <Entity, bool> mappedSelector = ConvertExpression (match); IList <Entity> tList = await baseBLL. findAsync (mappedSelector); IList <DTO> collection = tList. mapToList <Entity, DTO> (); return await Task <IList <DTO>. fromResult (collection );}
In this way, we can use the LINQ expression of the Entity Framework object Framework for queries.
3. Multi-condition Processing
In the preceding query code, we noticed that there is only one condition in the condition, as shown in the following code.
private ExpressionNode GetCondtionSql() { Expression<Func<DictDataInfo, bool>> expression = p => p.DictType_ID == this.lblDictType.Tag.ToString(); var queryNode = expression.ToExpressionNode(); return queryNode; }
If there are multiple conditions, special processing is required. Otherwise, multiple conditions cannot be combined for query. What is the processing of multiple conditions?
For example, for the log query interface, If a conditional statement is used, you need to use the following code assembly statement to obtain data through the interface method.
/// <Summary> /// construct a query statement based on the query conditions /// </summary> private string GetConditionSql () {SearchCondition condition = new SearchCondition (); condition. addCondition ("LoginName", this.txt LoginName. text, SqlOperator. like); condition. addCondition ("FullName", this.txt RealName. text, SqlOperator. like); condition. addCondition ("Note", this.txt Note. text, SqlOperator. like); condition. addCondition ("IPAddress", this.txt IPAddress. text, SqlOperator. like); condition. addCondition ("MacAddress", this.txt MacAddress. text, SqlOperator. like); if (dateTimePicker1.Text. length> 0) {condition. addCondition ("LastUpdated", Convert. toDateTime (dateTimePicker1.DateTime. toString ("yyyy-MM-dd"), SqlOperator. moreThanOrEqual);} if (dateTimePicker2.Text. length> 0) {condition. addCondition ("LastUpdated", Convert. toDateTime (dateTimePi Cker2.DateTime. AddDays (1). ToString ("yyyy-MM-dd"), SqlOperator. LessThanOrEqual);} string systemType = this.txt SystemType. GetComboBoxValue (); if (! String. isNullOrEmpty (systemType) {condition. addCondition ("SystemType_ID", systemType, SqlOperator. equal);} // Add the company ID if (Portal. gc. userInRole (RoleInfo. companyAdminName) {condition. addCondition ("Company_ID", Portal. gc. userInfo. company_ID, SqlOperator. equal);} string where = condition. buildConditionSql (). replace ("Where", ""); // if the condition is obtained by clicking a node, use the tree list. Otherwise, use the if (! String. IsNullOrEmpty (treeConditionSql) {where = treeConditionSql;} return where ;}
There are many conditions here. Through the SearchCondition object, we can easily combine queries with multiple conditions and then generate the required condition statements. In the Entity Framework, if we need to use the Lamda expression, how should we construct the object and pass it into the interface method? The Code is as follows.
/// <Summary> /// construct a query statement based on the query conditions /// </summary> private ExpressionNode GetConditionSql () {Expression <Func <LoginLogInfo, bool> expression = p => true; if (! String.IsNullOrEmpty(this.txt LoginName. Text) {expression = expression. And (x => x.LoginName.Contains(this.txt LoginName. Text);} if (! String.IsNullOrEmpty(this.txt RealName. Text) {expression = expression. And (x => x.FullName.Contains(this.txt RealName. Text);} if (! String.IsNullOrEmpty(this.txt Note. Text) {expression = expression. And (x => x.Note.Contains(this.txt Note. Text);} if (! String.IsNullOrEmpty(this.txt IPAddress. Text) {expression = expression. And (x => x.IPAddress.Contains(this.txt IPAddress. Text);} if (! String.IsNullOrEmpty(this.txt MacAddress. text) {expression = expression. and (x => x.MacAddress.Contains(this.txt MacAddress. text);} if (dateTimePicker1.Text. length> 0) {expression = expression. and (x => x. lastUpdated> = Convert. toDateTime (dateTimePicker1.DateTime. toString ("yyyy-MM-dd");} if (dateTimePicker2.Text. length> 0) {expression = expression. and (x => x. lastUpdated <= Convert. toDateTime (DateTimePicker2.DateTime. AddDays (1). ToString ("yyyy-MM-dd");} string systemType = this.txt SystemType. GetComboBoxValue (); if (! String. isNullOrEmpty (systemType) {expression = expression. and (x => x. systemType_ID = systemType);} // Add the company ID if (Portal. gc. userInRole (RoleInfo. companyAdminName) {expression = expression. and (x => x. company_ID = Portal. gc. userInfo. company_ID);} // if the condition is obtained by clicking the node, use the tree list. Otherwise, use the if (treeCondition! = Null) {expression = treeCondition;} return expression. ToExpressionNode ();}
Here we notice expression. and or expression. or function, which is not the method of this expression object. It is an extension class function for this object. It specifically handles the extension of the Lamda-Expression expression and facilitates the combination of multiple conditions,For example, two expression conditions can be combined into and or conditions.
In this way, we can bind the data processing method when processing the interface as follows.
Public void BindData () {# region add alias parsing this. winGridViewPager1.DisplayColumns = "ID, User_ID, LoginName, FullName, Company_ID, CompanyName, Note, IPAddress, MacAddress, SystemType_ID, LastUpdated"; this. winGridViewPager1.ColumnNameAlias = CallerFactory <ILoginLogService>. instance. getColumnNameAlias (); // escape the name of the field column # endregion ExpressionNode where = GetConditionSql (); PagerInfo = this. winGridViewPager1.PagerInfo; IList <LoginLogInfo> list = CallerFactory <ILoginLogService>. instance. findWithPager (where, ref PagerInfo); this. winGridViewPager1.DataSource = new WHC. pager. winControl. sortableBindingList <LoginLogInfo> (list );}
The above is my interface operations on the mixed Entity Framework object Framework. I have summarized several analysis scenarios and hope to help you understand the methods of using the Entity Framework in the WCF mode.
This series of articles is as follows:
Entity Framework formation journey -- Entity Framework based on generic warehousing model (1)
Entity Framework formation tour-using Unity object dependency injection to optimize Entity Framework (2)
The formation of Entity Framework object Framework -- Implementation of unified and asynchronous operations of basic interfaces (3)
Entity Framework formation journey-processing of Entity Data Model (EDM) (4)
Entity Framework object Framework formation journey -- Code First Framework Design (5)
Entity Framework object Framework formation journey -- using Fluent API configuration in Code First mode (6)
The formation of Entity Framework -- separation and combination of data transmission model DTO and Entity model Entity
Entity Framework object Framework formation journey-typical processing of interface operations (8)