[はじめに]
みなさん、こんにちは、私はTANZAMEです。天候はクーラーを取得している驚くべきことに、我々は再び会った冬の日の開始前に、友人は暖かく、快適なラインとコードを保つために服を追加するために注意を払います。距離TZM.XFrameworkの デビューは、より多くの数ヶ月以上、我々は深く感謝に関しては、励まし、アドバイスやフィードバックの間に多くの友人を受けています。
多くの見物人が、多くの場合、.NET EFの下で正式私の友人、良いO / RMシステムを持っている疑問を、第三者が持っているlinq2dbを (海外)、StackExchange / Dapperの (海外)、NHibernateは (海外)、PetaPoco (海外)、Freesql (国内)というように、あなたの問題は何ですか?[OK]を、私たちは分で行くことは私の話は何の利点、コードをよりエレガントでより爽快にするためにORMを使用する方法についての話。
[テキスト]
私は友人がこのシナリオを経験していると信じて:あなたは/削除/挿入する外部キーテーブルからデータを変更したい、どのようにしますか?それが取った行動はさらに出て最初のチェックは、そう古い鉄、少なくとも二回以上のデータベースアクセスは、性能の観点から最善のアプローチではありませんありません。SQL純粋なラインと手が、それは少なくとも、それほど不快ではない大丈夫に見えます。そこに、このようなAラインがあり、我々はORM SQLを助けることができる場合は、どのくらい多くの幸せ?ORMは、私たちがどのように動作するかを見ることです。
1.多対応テーブル更新
//更新本表值等于别表的字段值 VARクエリ= context.GetTable <Model.Client>()内から a.CloudServerIdにcontext.GetTable <Model.CloudServer>()のBに参加等しいb.CloudServerIdが 参加しますa.ClientIdにcontext.GetTable <Model.ClientAccount>()におけるcがc.ClientId等しい c.AccountIdが== "1" を選択します。 context.Update <Model.Client、Model.CloudServer、Model.ClientAccount>((A、B、C)=>新しい { CloudServerId = b.CloudServerId、 数量= c.Qty> 0 c.Qty:1、 }、クエリ); context.SubmitChanges(); -产生的SQL --update T0 SET --t0 [CloudServerId] = T1 [CloudServerId]、。。 。。--t0 [数量] =(CASE T2 [数量]> @ P1 THEN T2。 --from [Bas_Client]と[T 0] --INNER JOIN [Sys_CloudServer] T1 ON T0 [CloudServerId] = T1 [CloudServerId] --INNERがJOIN [Bas_ClientAccount] T2 ON T0 [ClientIdを] = T2 [ClientIdを】 --where T2 [たAccountId] = @ P3
慎重context.GetTableでから、対応するSQLクエリセマンティクスを観察し、困難見つけるために、この文は正確にテーブルから*** UPDAEにこれを対応し、次のステップは、外部キーテーブルを関連付けることで、INNERは最終的に、TABLEに参加します私たちは、WHERE句に精通しています。それはOracleのUPDATEが唯一の代わりにマージして、この構文からのものではないという特別な場所があります。どのように達成するためにされたソースコードを見てみましょう:
例えばT0、T1、のT2形として表さ、B、C変数としてクエリセマンティクスにおける//事前解決テーブルエイリアスが表示され、 TableAliasCache this.PrepareAliasエイリアス= <T>(uQueryInfo.SelectInfo、トークン); ExpressionVisitorBaseは=ヒットNULL; //解析UPDATEフィールドは 新しい新しいUpdateExpressionVisitorを打つ=(これ、別名、uQueryInfo.Expression); visitor.Write(ビルダー); //フラグメントFROM builder.AppendNewLine(); builder.append( "FROM"); ビルダー。 AppendMember(typeRuntime.TableName、typeRuntime.IsTemporary!); builder.AppendAs( "T0"); VAR = CMD2新しい新MappingCommand(これ、別名、トークン)= {hasManyのuQueryInfo.SelectInfo.HasMany}; //は、外部キーテーブルの解析 訪問者を新新=(これ、別名、uQueryInfo.SelectInfo.Joins)JoinExpressionVisitor; visitor.Write(cmd2.JoinFragment)。 // WHERE条件の解析 =新しい新しいWhereExpressionVisitorの訪問者(これは、別名、uQueryInfo.SelectInfo.WhereExpression); visitor.Write(cmd2.WhereFragment); cmd2.AddNavMembers(visitor.NavMembersが); //すべてのピースがついに最終SQL文合併し builder.Appendを(CMD2 .CommandText);
2.マルチ対応テーブルを挿入します
//多表关联批量新增 VARクエリ= からでcontext.GetTable <Model.Client>()は a.CloudServerIdにcontext.GetTable <Model.CloudServer>()のBに参加b.CloudServerId等しい 場合a.ClientIdを< = 5 && b.CloudServerId!= 0 を選択し、新しいModel.Client { ClientIdを= DbFunction.RowNumber <整数>(X => a.ClientId)+(maxClientId + 2)、 ClientCode = "ABC2"、 CLIENTNAME =「啊啵呲2" 、 CloudServerId = b.CloudServerId、 STATE = 2、 ActiveDate = DateTime.Now }。 context.Insert(クエリ); -产生的SQL --insert INTO [Bas_Client]([ClientIdを]、[ClientCode]、[CLIENTNAME]、[CloudServerId]、[状態]、 --select --ROW_NUMBER()オーバー(秩序t0の[ClientIdを]。)+ @ P17 + P18 @ AS [ClientIdを]、 - [ClientCode] AS @ P19、 - P20 AS [クライアント名]、@ --t1 [CloudServerId] AS [CloudServerId]、。- P21 AS [状態]、@ P22 @ AS [ActiveDate] - --from 【Bas_Client] T0 --INNER [Sys_CloudServer]がT1 ON T0 [CloudServerId] = T1をJOIN [CloudServerId] --where T0 [ClientIdを<= @ P23およびT1 [CloudServerId <> P24 @
最初の行のINSERTを除去するために生成されたSQLから分かるように、残りの部分は全体SELECT文であり、クエリセマンティクスすなわち、例えば上記のコードクエリ変数を表します。SELECT文を解析中にフィールドが記録されるべきであることに留意すべきである、INSERT INTOステートメントは、これらのフィールドの上にステッチが必要です。達成するためのコードを見てください:
// INSERT INTO片断 builder.Append( "INSERT INTO"); builder.AppendMember(typeRuntime.TableName、typeRuntime.IsTemporary!)。 builder.Append( '('); //解析块SELECT MappingCommandとしてMappingCommand CMD2 = this.ParseSelectCommand(nQueryInfo.SelectInfo、0、trueの場合、トークン); int型私は= 0; //拼接INSERT INTO字段 でforeachの(列column cmd2.PickColumns) { builder.AppendMember(column.NewName); IF(I <cmd2.PickColumns.Count - 1)builder.Append( ' '); I ++; } builder.Append(')')。 //最后合并所有的片断形成最终SQL语句 builder.AppendNewLine(); builder.Append(cmd2.CommandText)。
3.マルチ関連付けられたテーブルを削除します
//クエリ关联批量删除
VARクエリ=
context.GetTable <Model.Client>()内から
a.ClientId上context.GetTable <Model.ClientAccount>()でBに参加b.ClientIdが等しい
context.GetTableでCに参加<新しい{b.ClientId、b.AccountId}にModel.ClientAccountMarketは>(){c.ClientId、c.AccountId}新規に等しい
場合c.ClientId> 100 && c.AccountId == "1" && c.MarketId == 1
を選択;
context.Delete <Model.Client>(Query1を)。
-产生的SQL
--delete t0から[Bas_Client] T0
。--INNER JOIN [Bas_ClientAccount] T1 ON T0 [ClientIdを] = T1 [ClientIdを]
。--INNER JOIN [Bas_ClientAccountMarket】T2のT1 [ClientIdを] = T2 [ClientIdを]およびT1 [たAccountId] = T2 [たAccountId]
--where T2 [ClientIdを】> @ P2およびT2 [たAccountId。 ] = @ P3およびT2 [MarketId] = @ P4
原則と削除、更新の更新はUPDATEがDELETE置き換え以上同じ、何もありません。また、Oracleは文法から、削除しませんでした、削除に関連した効果を達成するように、我々はROWIDと、トリッキーなビットを変更します。最後に、達成するためのコードを見てみましょう:
//フラグメントFROM DELETE builder.append( "DELETE T0から"); builder.AppendMember(typeRuntime.TableName、typeRuntime.IsTemporary!); Builder.append( "T0"); //事前の解析テーブルの別名、クエリのセマンティクス変数として表される、B、Cは、T0、T1、T2の形表示される 。TableAliasCache this.PrepareAliasエイリアス= <T>(dQueryInfo.SelectInfo、トークン) (これは、エイリアス、トークン){hasManyのVAR = CMD2新しい新しいMappingCommandをdQueryInfo.SelectInfo.HasMany} =; //は、外部キーテーブル解析 ExpressionVisitorBaseは(これ、別名、dQueryInfo.SelectInfo.Joins)=新しい新しいJoinExpressionVisitorをヒットし、 visitor.Write(cmd2.JoinFragment); //解析条件 ビジター=新しいWhereExpressionVisitor(この、別名、dQueryInfo.SelectInfo.WhereExpression); visitor.Write(cmd2.WhereFragment)。 cmd2.AddNavMembers(visitor.NavMembers); //すべての作品は、最終的には、最終的なSQL文合併し builder.Append(cmd2.CommandTextを)。
[結論]
GitHubのホスティング住所:大型ヶ月半の努力によって、TZM.XFrameworkも正式にSQLiteの、およびホスティングアドレスをサポートhttps://github.com/TANZAME/XFrameworkを 。最後に、公共の言葉の一定数以上の借入とは、あなたが面白いと他人を喜ばせるために役立つことができ前に自分を喜ばせるために互いに、楽しさと好奇心を奨励します。簡単ヤードラインではなく、光のスプレーのように、古い友人の交換を歓迎プラスグループの異なるビューがありません。
技術交流グループ:816 425 449