.NET在EF中使用sql炕贵,用動態(tài)類吧梆奈!

前言

在.NET中使用Entity Framework能快速、方便地結(jié)合LINQ來對數(shù)據(jù)庫進行一系列的增刪改查操作称开。但是由于EF根據(jù)表達式最后生成通用的sql來執(zhí)行亩钟,進行具體的數(shù)據(jù)庫操作。根據(jù)本人使用EF的經(jīng)驗鳖轰,對于增清酥、刪、改的操作蕴侣,可以直接使用EF的接口進行快速開發(fā)焰轻。但是對于查詢的操作,最好是使用EF調(diào)用sql來操作昆雀。

問題呈現(xiàn)

在EF中調(diào)用sql進行數(shù)據(jù)查詢后辱志,需要返回一個指定類型的數(shù)據(jù)列表练湿,那么這個類型是需要在調(diào)用的時候指定的藐守。我們就會遇到這種問題:我只需要查一些簡單的數(shù)據(jù),例如查詢一下符合某條件的數(shù)據(jù)數(shù)量等等疚宇,就必須新建一個類型客冈,增加了程序的冗余度。

解決方案

需要實現(xiàn)動態(tài)生成類的方法稳强,可以插入屬性名稱和屬性類型场仲,返回一個類型,提供給EF使用退疫。

實現(xiàn)

//該類是用于定義屬性節(jié)點的渠缕,包括屬性的名稱、屬性的類型褒繁。
public class PropertyItem
    {
        public PropertyItem(string name, Type type)
        {
            this.Name = name;
            this.Type = type;
        }

        public string Name { set; get; }
        public Type Type { set; get; }
    }

     
//該類是提供接口亦鳞,動態(tài)生成類型的。
public class UserTypeFactory
    {
        public static Type GetUserType(params PropertyItem[] itemList)
        {
            TypeBuilder builder = CreateTypeBuilder(
                    "MyDynamicAssembly", "MyModule", "MyType");
            foreach(var item in itemList)
            {
                CreateAutoImplementedProperty(builder, item.Name, item.Type);
            }

            Type resultType = builder.CreateType();
            return resultType;
        }

        private static TypeBuilder CreateTypeBuilder( 
            string assemblyName, string moduleName, string typeName)
        {
            TypeBuilder typeBuilder = AppDomain
                .CurrentDomain
                .DefineDynamicAssembly(new AssemblyName(assemblyName),
                                       AssemblyBuilderAccess.Run)
                .DefineDynamicModule(moduleName)
                .DefineType(typeName, TypeAttributes.Public);
            typeBuilder.DefineDefaultConstructor(MethodAttributes.Public);
            return typeBuilder;
        }

        private static void CreateAutoImplementedProperty(
            TypeBuilder builder, string propertyName, Type propertyType)
        {
            const string PrivateFieldPrefix = "m_";
            const string GetterPrefix = "get_";
            const string SetterPrefix = "set_";

            // 定義字段.
            FieldBuilder fieldBuilder = builder.DefineField(
                string.Concat(PrivateFieldPrefix, propertyName),
                              propertyType, FieldAttributes.Private);

            // 定義屬性
            PropertyBuilder propertyBuilder = builder.DefineProperty(
                propertyName, System.Reflection.PropertyAttributes.HasDefault, propertyType, null);

            // 屬性的getter和setter的特性
            MethodAttributes propertyMethodAttributes =
                MethodAttributes.Public | MethodAttributes.SpecialName |
                MethodAttributes.HideBySig;

            // 定義getter方法
            MethodBuilder getterMethod = builder.DefineMethod(
                string.Concat(GetterPrefix, propertyName),
                propertyMethodAttributes, propertyType, Type.EmptyTypes);

            ILGenerator getterILCode = getterMethod.GetILGenerator();
            getterILCode.Emit(OpCodes.Ldarg_0);
            getterILCode.Emit(OpCodes.Ldfld, fieldBuilder);
            getterILCode.Emit(OpCodes.Ret);

            // 定義setter方法
            MethodBuilder setterMethod = builder.DefineMethod(
                string.Concat(SetterPrefix, propertyName),
                propertyMethodAttributes, null, new Type[] { propertyType });


            ILGenerator setterILCode = setterMethod.GetILGenerator();
            setterILCode.Emit(OpCodes.Ldarg_0);
            setterILCode.Emit(OpCodes.Ldarg_1);
            setterILCode.Emit(OpCodes.Stfld, fieldBuilder);
            setterILCode.Emit(OpCodes.Ret);

            propertyBuilder.SetGetMethod(getterMethod);
            propertyBuilder.SetSetMethod(setterMethod);
        }

    }

使用

YmsEntities entities=new YmsEntities();
dynamic studentDic= entities.Database.SqlQuery(UserTypeFactory.GetUserType(new PropertyItem("ID", typeof(int)), new PropertyItem("num", typeof(string))),"select ID ,Name as num from student");
foreach (var student in studentDic)
{
  //業(yè)務(wù)
  var id=student.ID;
  var num=student.num;
}

補充

還有另外一種方式能實現(xiàn):

public MainWindow()
{
   InitializeComponent();
           
   hjf_jianzhengEntities entity = new hjf_jianzhengEntities();
   var context = ((IObjectContextAdapter)entity).ObjectContext;
   var result = new ObjectQuery<DbDataRecord>("Select dic_Town.CNAME from dic_Town", context).ToList();
   var s=result.First()[0];
 }

  • 該方法優(yōu)點是不用定義多余的參數(shù)、類型燕差、字段名遭笋。
  • 缺點是select語句中不能用”*“,并且字段必須帶上表明徒探,例如dic_Town.CNAME瓦呼。
補充一個第三方提供的工具,github地址:https://github.com/StackExchange/dapper-dot-net
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末测暗,一起剝皮案震驚了整個濱河市央串,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌碗啄,老刑警劉巖质和,帶你破解...
    沈念sama閱讀 218,451評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異稚字,居然都是意外死亡饲宿,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,172評論 3 394
  • 文/潘曉璐 我一進店門尉共,熙熙樓的掌柜王于貴愁眉苦臉地迎上來褒傅,“玉大人,你說我怎么就攤上這事袄友〉钔校” “怎么了?”我有些...
    開封第一講書人閱讀 164,782評論 0 354
  • 文/不壞的土叔 我叫張陵剧蚣,是天一觀的道長支竹。 經(jīng)常有香客問我,道長鸠按,這世上最難降的妖魔是什么礼搁? 我笑而不...
    開封第一講書人閱讀 58,709評論 1 294
  • 正文 為了忘掉前任,我火速辦了婚禮目尖,結(jié)果婚禮上馒吴,老公的妹妹穿的比我還像新娘。我一直安慰自己瑟曲,他們只是感情好饮戳,可當(dāng)我...
    茶點故事閱讀 67,733評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著洞拨,像睡著了一般扯罐。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上烦衣,一...
    開封第一講書人閱讀 51,578評論 1 305
  • 那天歹河,我揣著相機與錄音掩浙,去河邊找鬼。 笑死秸歧,一個胖子當(dāng)著我的面吹牛厨姚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播寥茫,決...
    沈念sama閱讀 40,320評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼遣蚀,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了纱耻?” 一聲冷哼從身側(cè)響起芭梯,我...
    開封第一講書人閱讀 39,241評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎弄喘,沒想到半個月后玖喘,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,686評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡蘑志,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,878評論 3 336
  • 正文 我和宋清朗相戀三年累奈,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片急但。...
    茶點故事閱讀 39,992評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡澎媒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出波桩,到底是詐尸還是另有隱情戒努,我是刑警寧澤,帶...
    沈念sama閱讀 35,715評論 5 346
  • 正文 年R本政府宣布镐躲,位于F島的核電站储玫,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏萤皂。R本人自食惡果不足惜撒穷,卻給世界環(huán)境...
    茶點故事閱讀 41,336評論 3 330
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望裆熙。 院中可真熱鬧端礼,春花似錦、人聲如沸入录。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,912評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽纷跛。三九已至,卻和暖如春邀杏,著一層夾襖步出監(jiān)牢的瞬間贫奠,已是汗流浹背唬血。 一陣腳步聲響...
    開封第一講書人閱讀 33,040評論 1 270
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留唤崭,地道東北人拷恨。 一個月前我還...
    沈念sama閱讀 48,173評論 3 370
  • 正文 我出身青樓,卻偏偏與公主長得像谢肾,于是被迫代替她去往敵國和親腕侄。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,947評論 2 355

推薦閱讀更多精彩內(nèi)容