Entity Framework 實(shí)體框架的形成之旅--界面操作的幾個典型的處理(8)

在上篇隨筆《Entity Framework 實(shí)體框架的形成之旅--數(shù)據(jù)傳輸模型DTO和實(shí)體模型Entity的分離與聯(lián)合》里面笤受,介紹了在Entity Framework 實(shí)體框架里面引入了DTO的對象,通過數(shù)據(jù)傳輸模型DTO和實(shí)體模型Entity的分離與聯(lián)合倘潜,很好的隔離了它們的關(guān)系博烂,使得即使是復(fù)雜的實(shí)體模型Entity绒瘦,也不會影響WCF接口數(shù)據(jù)的傳輸和處理涛碑。本文主要介紹在基于這個分離模型的基礎(chǔ)上壁袄,如何在界面實(shí)現(xiàn)多種常規(guī)的處理操作。

1豆混、常規(guī)業(yè)務(wù)的增加篓像、更新操作

對于業(yè)務(wù)對象的增加,由于我們引入了DTO對象皿伺,因此在界面的處理端员辩,肯定也是利用了DTO對象進(jìn)行的,如下代碼是增加鸵鸥、修改的處理操作處理奠滑。

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;
}

上面的操作,和我之前的混合框架的使用代碼是差不多的妒穴,原來的基于EnterpriseLibrary架構(gòu)的框架宋税,實(shí)體類采用的就是 "表名+Info" 的方式,雖然這里的**Info代表DTO對象讼油,是實(shí)體框架的Entity對象的映射類杰赛,不過總體業(yè)務(wù)上的處理代碼是差不多的了,這也是我希望看到比較平滑過渡和容易理解的改變之一矮台。

2乏屯、基于DTO表達(dá)式的查詢處理

如果對于查詢根时,我們知道,如果使用字符串的條件表達(dá)式辰晕,一般也是可以實(shí)現(xiàn)處理操作的蛤迎,不過就是需要硬編碼SQL語句,對于一些安全性高一點(diǎn)的處理含友,可能不太好替裆,由于實(shí)體框架可以采用Lamda表達(dá)式來進(jìn)行查詢,那么我們是否也可以在界面采用Lamda表達(dá)式來替代條件的SQL語句呢窘问?
我們知道辆童,上篇隨筆已經(jīng)介紹了引入DTO對象,用來解耦實(shí)體框架的對象模型南缓,如下所示的模塊分層場景胸遇。



這樣我們在設(shè)計BLL業(yè)務(wù)邏輯層的時候,肯定還是可以使用實(shí)體框架的Expression<Func<T, bool>>表達(dá)式的汉形,如IBLL層的接口定義對于Expression表達(dá)式的使用接口如下所示纸镊。

/// <summary>
/// 根據(jù)條件查詢數(shù)據(jù)庫,并返回對象集合
/// </summary>
/// <param name="match">條件表達(dá)式</param>
/// <returns></returns>
IList<T> Find(Expression<Func<T, bool>> match);

/// <summary>
/// 根據(jù)條件表達(dá)式返回可查詢的記錄源
/// </summary>
/// <param name="match">查詢條件</param>
/// <param name="sortPropertyName">排序?qū)傩悦Q</param>
/// <param name="isDescending">如果為true則為降序,否則為升序</param>
/// <returns></returns>
IQueryable<T> GetQueryable(Expression<Func<T, bool>> match, string sortPropertyName, bool isDescending = true);

不過在門面層Facade層就不能繼續(xù)使用了這種Expression<Func<T, bool>>表達(dá)式的了概疆,同時也不能在Facade層使用IQueryable<T>接口逗威,因?yàn)閃CF服務(wù)無法序列化這個接口的。
那基于這個原因岔冀,我們應(yīng)該如何傳遞Expression<Func<T, bool>> match這個條件參數(shù)的表達(dá)式呢凯旭,答案是引入Serialize.Linq組件,使用ExpressionNode對象進(jìn)行承載使套,最后再把它解析為Expression<Func<T, bool>> match進(jìn)行處理就可以了罐呼。

/// <summary>
/// 根據(jù)條件查詢數(shù)據(jù)庫,并返回對象集合
/// </summary>
/// <param name="match">條件表達(dá)式</param>
/// <returns></returns>
[OperationContract(Name = "Find")]
IList<DTO> Find(ExpressionNode match);

/// <summary>
/// 根據(jù)條件查詢數(shù)據(jù)庫,并返回對象集合(異步)
/// </summary>
/// <param name="match">條件表達(dá)式</param>
/// <returns></returns>
[OperationContract(Name = "FindAsync")]
Task<IList<DTO>> FindAsync(ExpressionNode match);

我們在客戶端界面里面處理的話,就需要構(gòu)建一個ExpressionNode對象侦高,查詢處理代碼如下所示嫉柴。

這里主要需要先從Expression<Function<T,boo>>到ExpressionNode,通過調(diào)用expression.ToExpressionNode();進(jìn)行處理得到奉呛,如下代碼所示计螺。

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 添加別名解析
    this.winGridViewPager1.DisplayColumns = "Name,Value,Seq,Remark,EditTime";
    this.winGridViewPager1.AddColumnAlias("ID", "編號");
    this.winGridViewPager1.AddColumnAlias("DictType_ID", "字典大類");
    this.winGridViewPager1.AddColumnAlias("Name", "項(xiàng)目名稱");
    this.winGridViewPager1.AddColumnAlias("Value", "項(xiàng)目值");
    this.winGridViewPager1.AddColumnAlias("Seq", "字典排序");
    this.winGridViewPager1.AddColumnAlias("Remark", "備注");
    this.winGridViewPager1.AddColumnAlias("Editor", "修改用戶");
    this.winGridViewPager1.AddColumnAlias("EditTime", "更新日期");
    #endregion

    if (this.lblDictType.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);
    }
}

我們在Facade接口實(shí)現(xiàn)端,就需要把ExpressionNode反過來變成Expression<Function<T,boo>>對象瞧壮。

/// <summary>
/// 根據(jù)條件查詢數(shù)據(jù)庫,并返回對象集合
/// </summary>
/// <param name="match">條件表達(dá)式</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>
/// 根據(jù)條件查詢數(shù)據(jù)庫,并返回對象集合(異步)
/// </summary>
/// <param name="match">條件表達(dá)式</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);
}

這樣我們就可以很好利用Entity Framework 實(shí)體框架的LINQ表達(dá)式進(jìn)行查詢了登馒。

3、多條件的處理方式

上面的查詢代碼里面咆槽,我們注意到了陈轿,條件里面只有一個條件,如下代碼。

private ExpressionNode GetCondtionSql()
{
    Expression<Func<DictDataInfo, bool>> expression = p => p.DictType_ID == this.lblDictType.Tag.ToString();
    var queryNode = expression.ToExpressionNode();
    return queryNode;
}

那么對于有多個條件的話济欢,處理就需要特殊處理了赠堵,否則就沒法組合多個條件進(jìn)行查詢了小渊,多個條件的處理是如何的呢法褥?
如對于日志查詢界面來說,如果是采用條件語句的方式酬屉,需要使用下面的代碼組裝語句半等,然后通過接口方法進(jìn)行獲取數(shù)據(jù)。

/// <summary>
/// 根據(jù)查詢條件構(gòu)造查詢語句
/// </summary> 
private string GetConditionSql()
{
    SearchCondition condition = new SearchCondition();
    condition.AddCondition("LoginName", this.txtLoginName.Text, SqlOperator.Like);
    condition.AddCondition("FullName", this.txtRealName.Text, SqlOperator.Like);
    condition.AddCondition("Note", this.txtNote.Text, SqlOperator.Like);
    condition.AddCondition("IPAddress", this.txtIPAddress.Text, SqlOperator.Like);
    condition.AddCondition("MacAddress", this.txtMacAddress.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(dateTimePicker2.DateTime.AddDays(1).ToString("yyyy-MM-dd")), SqlOperator.LessThanOrEqual);
    }

    string systemType = this.txtSystemType.GetComboBoxValue();
    if (!string.IsNullOrEmpty(systemType))
    {
        condition.AddCondition("SystemType_ID", systemType, SqlOperator.Equal);
    }

    //如果是公司管理員呐萨,增加公司標(biāo)識
    if (Portal.gc.UserInRole(RoleInfo.CompanyAdminName))
    {
        condition.AddCondition("Company_ID", Portal.gc.UserInfo.Company_ID, SqlOperator.Equal);
    }

    string where = condition.BuildConditionSql().Replace("Where", "");
    //如果是單擊節(jié)點(diǎn)得到的條件杀饵,則使用樹列表的,否則使用查詢條件的
    if (!string.IsNullOrEmpty(treeConditionSql))
    {
        where = treeConditionSql;
    }
    return where;
}

這里有很多條件谬擦,通過 SearchCondition 對象切距,我們能夠很方便組合多個條件的查詢,然后生成所需的條件語句就可以了惨远,那么對于實(shí)體框架里面谜悟,我們需要采用Lamda表達(dá)式的話,應(yīng)該如何構(gòu)建對象并傳入給接口方法呢北秽,代碼如下所示葡幸。

/// <summary>
/// 根據(jù)查詢條件構(gòu)造查詢語句
/// </summary> 
private ExpressionNode GetConditionSql()
{
    Expression<Func<LoginLogInfo, bool>> expression = p => true;
    if (!string.IsNullOrEmpty(this.txtLoginName.Text))
    {
        expression = expression.And(x => x.LoginName.Contains(this.txtLoginName.Text));
    }
    if (!string.IsNullOrEmpty(this.txtRealName.Text))
    {
        expression = expression.And(x => x.FullName.Contains(this.txtRealName.Text));
    }
    if (!string.IsNullOrEmpty(this.txtNote.Text))
    {
        expression = expression.And(x => x.Note.Contains(this.txtNote.Text));
    }
    if (!string.IsNullOrEmpty(this.txtIPAddress.Text))
    {
        expression = expression.And(x => x.IPAddress.Contains(this.txtIPAddress.Text));
    }
    if (!string.IsNullOrEmpty(this.txtMacAddress.Text))
    {
        expression = expression.And(x => x.MacAddress.Contains(this.txtMacAddress.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.txtSystemType.GetComboBoxValue();
    if (!string.IsNullOrEmpty(systemType))
    {
        expression = expression.And(x => x.SystemType_ID == systemType);
    }

    //如果是公司管理員,增加公司標(biāo)識
    if (Portal.gc.UserInRole(RoleInfo.CompanyAdminName))
    {
        expression = expression.And(x => x.Company_ID == Portal.gc.UserInfo.Company_ID);
    }

    //如果是單擊節(jié)點(diǎn)得到的條件贺氓,則使用樹列表的蔚叨,否則使用查詢條件的
    if (treeCondition != null)
    {
        expression = treeCondition;
    }
    return expression.ToExpressionNode();
}

這里我們注意到expression.And或者expression.Or函數(shù),它不是這個expression對象的方法的辙培,是我們針對這個做的一個擴(kuò)展類函數(shù)蔑水,它專門處理 Lamda-Expression表達(dá)式的擴(kuò)展,方便組合多個條件扬蕊,如兩個表達(dá)式條件可以組合為AND或者OR條件方式搀别。


這樣我們在界面處理的時候,綁定數(shù)據(jù)的處理方法就可以如下所示了厨相。

public void BindData()
{
    #region 添加別名解析
    this.winGridViewPager1.DisplayColumns = "ID,User_ID,LoginName,FullName,Company_ID,CompanyName,Note,IPAddress,MacAddress,SystemType_ID,LastUpdated";
    this.winGridViewPager1.ColumnNameAlias = CallerFactory<ILoginLogService>.Instance.GetColumnNameAlias();//字段列顯示名稱轉(zhuǎn)義

    #endregion

    ExpressionNode where = GetConditionSql();
    PagerInfo PagerInfo = this.winGridViewPager1.PagerInfo;
    IList<LoginLogInfo> list = CallerFactory<ILoginLogService>.Instance.FindWithPager(where, ref PagerInfo);
    this.winGridViewPager1.DataSource = new WHC.Pager.WinControl.SortableBindingList<LoginLogInfo>(list);
}

以上就是我對于混合型的Entity Framework 實(shí)體框架的界面操作领曼,總結(jié)的幾種分析場景,希望對大家理解在WCF模式里面蛮穿,使用實(shí)體框架的方法有所幫助庶骄。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市践磅,隨后出現(xiàn)的幾起案子单刁,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件羔飞,死亡現(xiàn)場離奇詭異肺樟,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)逻淌,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進(jìn)店門么伯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人卡儒,你說我怎么就攤上這事田柔。” “怎么了骨望?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵硬爆,是天一觀的道長。 經(jīng)常有香客問我擎鸠,道長缀磕,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任劣光,我火速辦了婚禮袜蚕,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘赎线。我一直安慰自己廷没,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布垂寥。 她就那樣靜靜地躺著颠黎,像睡著了一般。 火紅的嫁衣襯著肌膚如雪滞项。 梳的紋絲不亂的頭發(fā)上狭归,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天,我揣著相機(jī)與錄音文判,去河邊找鬼过椎。 笑死,一個胖子當(dāng)著我的面吹牛戏仓,可吹牛的內(nèi)容都是我干的疚宇。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼赏殃,長吁一口氣:“原來是場噩夢啊……” “哼敷待!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起仁热,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤榜揖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體举哟,經(jīng)...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡思劳,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了妨猩。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片潜叛。...
    茶點(diǎn)故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖册赛,靈堂內(nèi)的尸體忽然破棺而出钠导,到底是詐尸還是另有隱情,我是刑警寧澤森瘪,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站票堵,受9級特大地震影響扼睬,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜悴势,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一窗宇、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧特纤,春花似錦军俊、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至昔穴,卻和暖如春镰官,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背吗货。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工泳唠, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人宙搬。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓笨腥,卻偏偏與公主長得像,于是被迫代替她去往敵國和親勇垛。 傳聞我的和親對象是個殘疾皇子脖母,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,486評論 2 348

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