EF 批量更新刪除(linq篇)


剛開始用EF很多東西都不會用,事后想想都很簡單的東西總是用很麻煩的方式實現

1:  EF的聯合查詢 inner join 

  很久很久以前我是這么寫一個列表展示的,其中有兩個字段Contractor和Maintaniner是需要inner join 鏈接查詢,

  但是當時太年輕不會用ef的鏈接,所以用了最笨的方法,代碼如下

      [Permission("L_Business")]
        public ActionResult Index(BusinessRequest request)
        {
            //合作商戶列表展示
            var result = this.MMService.GetBusinessList(request);
            result = this.GetContractorName(result);
            result = this.GetMaintainerName(result);
            return View(result);
        }
        /// <summary>
        /// 獲取創建者姓名
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        private IEnumerable<Business> GetContractorName(IEnumerable<Business> result)
        {
            foreach (var item in result)
            {
                var staff = this.OAService.GetStaff(item.ContractorID);
                if (staff != null) item.ConractorName = staff.Name;
            }
            return result;
        }
        /// <summary>
        /// 獲取創建者姓名
        /// </summary>
        /// <param name="result"></param>
        /// <returns></returns>
        private IEnumerable<Business> GetMaintainerName(IEnumerable<Business> result)
        {
            foreach (var item in result)
            {
                var staff = this.OAService.GetStaff(item.MaintainerID);
                if (staff != null) item.MaintainerName = staff.Name;
            }
            return result;
        }    

 

代碼很傻,需要循環多次去查出來每行中的Contractor和Maintaniner,這樣是很影響效率,同時顯得技術比較low的,下面的方式就好多了

首先:在model中設置鏈接外鍵

 public class Business : ModelBase
    {
  //簽約人ID
        public int ContractorID { get; set; }
        //外鍵指明要連接的表
        [ForeignKey("ContractorID")]
        public Staff Contractor { get; set; }


        //簽約日期
        public DateTime ContractDate { get; set; }
        //維護人員ID
        public int MaintainerID { get; set; }
        [ForeignKey("MaintainerID")]
        public Staff Maintainer { get; set; }
}

然后:在數據層中查詢時使用Include查詢

 public IEnumerable<Business> GetBusinessList(BusinessRequest request = null)
        {
            request = request ?? new BusinessRequest();
            using (var dbContext = new MMDbContext())
            {
                //include可以實現在model中設置的外檢鏈接 
                IQueryable<Business> business = dbContext.Business.Include("Contractor").Include("Maintainer");
                business = business.Where(b => b.IsDelete == 0);
                if (!string.IsNullOrEmpty(request.Name))
                {
                    business = business.Where(b => b.Name.Contains(request.Name));
                }
                return business.OrderByDescending(b => b.ID).ToPagedList(request.PageIndex, request.PageSize);
            }

        }

最后:在頁面展示的時候

 

 [Permission("L_Business")]
        public ActionResult Index(BusinessRequest request)
        {
            //合作商戶列表展示
            var result = this.MMService.GetBusinessList(request);
            
            return View(result);
        }
                        <td>
                            @(m.Contractor!=null?m.Contractor.Name:"")
                        </td>

                        <td>
                            @(m.Maintainer!=null?m.Maintainer.Name:"")
                        </td>        

但是用include 的時候用 SQL Server Profiler查看語句會發現第一個include和第二個不一樣

SELECT TOP (10) *
FROM ( SELECT [Extent1].[ID] AS [ID1], [Extent1].[Name] AS [Name1], [Extent1].[Address] AS [Address], [Extent1].[Contact] AS [Contact], [Extent1].[Mobile] AS [Mobile1], [Extent1].[BankID] AS [BankID], [Extent1].[BankAccount] AS [BankAccount], [Extent1].[AccountName] AS [AccountName], [Extent1].[AccountNumber] AS [AccountNumber], [Extent1].[ContractorID] AS [ContractorID], [Extent1].[ContractDate] AS [ContractDate], [Extent1].[MaintainerID] AS [MaintainerID], [Extent1].[Remark] AS [Remark1], [Extent1].[Status] AS [Status], [Extent1].[IsDelete] AS [IsDelete], [Extent1].[PayStatus] AS [PayStatus], [Extent1].[Balance] AS [Balance], [Extent1].[CreateDate] AS [CreateDate1], [Extent1].[CreateStaffID] AS [CreateStaffID1], [Extent1].[CreateStaffName] AS [CreateStaffName1], [Extent2].[ID] AS [ID2], [Extent2].[Number] AS [Number1], [Extent2].[Name] AS [Name2], [Extent2].[Mobile] AS [Mobile2], [Extent2].[MobileTwo] AS [MobileTwo1], [Extent2].[Gender] AS [Gender1], [Extent2].[Phone] AS [Phone1], [Extent2].[Remark] AS [Remark2], [Extent2].[Email] AS [Email1], [Extent2].[City] AS [City1], [Extent2].[Province] AS [Province1], [Extent2].[DeleteMark] AS [DeleteMark1], [Extent2].[IsActive] AS [IsActive1], [Extent2].[IsCreateAccount] AS [IsCreateAccount1], [Extent2].[ComeInDate] AS [ComeInDate1], [Extent2].[DepartureDate] AS [DepartureDate1], [Extent2].[CompanyID] AS [CompanyID1], [Extent2].[CreateDate] AS [CreateDate2], [Extent2].[CreateStaffID] AS [CreateStaffID2], [Extent2].[CreateStaffName] AS [CreateStaffName2], [Extent3].[ID] AS [ID3], [Extent3].[Number] AS [Number2], [Extent3].[Name] AS [Name3], [Extent3].[Mobile] AS [Mobile3], [Extent3].[MobileTwo] AS [MobileTwo2], [Extent3].[Gender] AS [Gender2], [Extent3].[Phone] AS [Phone2], [Extent3].[Remark] AS [Remark3], [Extent3].[Email] AS [Email2], [Extent3].[City] AS [City2], [Extent3].[Province] AS [Province2], [Extent3].[DeleteMark] AS [DeleteMark2], [Extent3].[IsActive] AS [IsActive2], [Extent3].[IsCreateAccount] AS [IsCreateAccount2], [Extent3].[ComeInDate] AS [ComeInDate2], [Extent3].[DepartureDate] AS [DepartureDate2], [Extent3].[CompanyID] AS [CompanyID2], [Extent3].[CreateDate] AS [CreateDate3], [Extent3].[CreateStaffID] AS [CreateStaffID3], [Extent3].[CreateStaffName] AS [CreateStaffName3], row_number() OVER (ORDER BY [Extent1].[ID] DESC) AS [row_number]
    FROM   [dbo].[MM_Business] AS [Extent1]
    INNER JOIN [dbo].[OA_Staff] AS [Extent2] ON [Extent1].[ContractorID] = [Extent2].[ID]
    LEFT OUTER JOIN [dbo].[OA_Staff] AS [Extent3] ON [Extent1].[MaintainerID] = [Extent3].[ID]
    WHERE 0 = [Extent1].[IsDelete]
)  AS [Filter1]
WHERE [Filter1].[row_number] > 0
ORDER BY [Filter1].[ID1] DESC

使用  SQL Server Profiler 檢測的native sql 顯示 第一次的include 為 inner join 第二個為left outer join,這里是一個知識盲點,以后還要在做研究

2:EF 多次更新和刪除

 圖樣圖森破,直接上代碼

        public void SaveBillAndOrder(Bill model, List<Order> orderList)
        {
            using (var dbContext = new WebSiteDbContext())
            {
                model = dbContext.Insert(model);
                //添加Order
                if (orderList.Count > 0)
                {
                    //增加訂單,使用循環方式添加一個
                    foreach (var item in orderList)
                    {
                        var entity = dbContext.Insert(item);
                    }
                }
                dbContext.SaveChanges();
            }
        }

這里展示一個code,是我在一個多次插入的例子,還有很多是批量刪除,批量更新都是用了foreach的方式

后來想,ef這么強大的工具不能就這樣吧,所以開始 百度

沒有包的同學可以直接nuget https://github.com/loresoft/EntityFramework.Extended

我的程序中用的是  EntityFramework.Extensions 自帶的,就沒有下載了

public void CancelRechargeCardPrepaymentByBillID(int BillID)
        {
            using (var dbContext = new WebSiteDbContext())
            {
                dbContext.RechargeCardPrepayments.Where(r => r.BillID == BillID).Update(r => new RechargeCardPrepayment { IsValid = (int)EnumRechargePrepaymentIsValid.WX });
                dbContext.SaveChanges();
            }
        }

實驗發現效率還是可以沒有出現每一條寫一個insert或者update 的情況(ps:刪除的話直接把Update換成Delete()就可以了)

Native sql 如下

exec sp_executesql N'UPDATE [dbo].[CRM_CardAndBalancePrepayment] SET 
[IsValid] = @p__update__0 
FROM [dbo].[CRM_CardAndBalancePrepayment] AS j0 INNER JOIN (
SELECT 
[Extent1].[ID] AS [ID]
FROM [dbo].[CRM_CardAndBalancePrepayment] AS [Extent1]
WHERE [Extent1].[BillID] = @p__linq__0
) AS j1 ON (j0.[ID] = j1.[ID])',N'@p__linq__0 int,@p__update__0 int',@p__linq__0=143817,@p__update__0=1

寫到這里腦海中突然想起了首歌:

 

  • 其實很簡單 其實很自然
  • 兩個人的愛由兩人分擔
  • 其實並不難 是你太悲觀
  • 隔着一道牆不跟誰分享

分享出來,哈哈哈哈,


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM