精品专区-精品自拍9-精品自拍三级乱伦-精品自拍视频-精品自拍视频曝光-精品自拍小视频

網(wǎng)站建設(shè)資訊

NEWS

網(wǎng)站建設(shè)資訊

EntityFramework.Extended如何用EF實(shí)現(xiàn)指定字段的更新

EntityFramework.Extended如何用EF實(shí)現(xiàn)指定字段的更新,相信很多沒有經(jīng)驗(yàn)的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。

成都創(chuàng)新互聯(lián)主要從事網(wǎng)站建設(shè)、成都網(wǎng)站制作、網(wǎng)頁設(shè)計(jì)、企業(yè)做網(wǎng)站、公司建網(wǎng)站等業(yè)務(wù)。立足成都服務(wù)烏蘇,十年網(wǎng)站建設(shè)經(jīng)驗(yàn),價格優(yōu)惠、服務(wù)專業(yè),歡迎來電咨詢建站服務(wù):028-86922220

今天在將一個項(xiàng)目中使用存儲過程的遺留代碼遷移至新的架構(gòu)時,遇到了一個問題——如何用EF實(shí)現(xiàn)數(shù)據(jù)庫中指定字段的更新(根據(jù)UserId更新Users表中的FaceUrl與AvatarUrl字段)?

原先調(diào)用存儲過程的代碼:

public bool UpdateAvatar(Guid userId, string faceUrl, string avatarUrl)
{
DbCommand command = _db.GetStoredProcCommand("User_UpdateFaceAvatar");
_db.AddInParameter(command, "@FaceUrl", DbType.String, faceUrl);
_db.AddInParameter(command, "@AvatarUrl", DbType.String, avatarUrl);
_db.AddInParameter(command, "@UserId", userId);
return _db.ExecuteNonQuery(command) > 0;
}

存儲過程中所使用的SQL語句:

UPDATE Users 
SET FaceUrl=@FaceUrl,AvatarUrl=@AvatarUrlWHERE [UserId]=@UserId

在新的架構(gòu)中,數(shù)據(jù)庫訪問用的是Entity Framework,并且用IUnitOfWork接口進(jìn)行了封裝,Application層對數(shù)據(jù)庫的操作是通過IUnitOfWork接口完成的。

IUnitOfWork接口是這么定義的:

public interface IUnitOfWork : IDisposable
{
IQueryable Set() where T : class;

T Add(T entity) where T : class;

IEnumerable AddRange(IEnumerable entities) where T : class;

T Attach(T entity) where T : class;

T Remove(T entity) where T : class;

IEnumerable RemoveRange(IEnumerable entities) where T : class;

bool Commit();

Task CommitAsync();
}

如果不給IUnitOfWork添加新的接口方法,可以使用EF的change tracking完成指定字段的更新操作。

Application.Services中的實(shí)現(xiàn)代碼:

public async Task UpdateFaceAvatar(Guid userId, string faceUrl, string avatarUrl)
{
var user = await _userRepository.GetByUserId(userId);
user.FaceUrl = faceUrl;
user.AvatarUrl = avatarUrl;
return await _unitOfWork.CommitAsync();
}

使用ef change tracking的優(yōu)點(diǎn)是如果屬性的值沒有被改變,就不會觸發(fā)數(shù)據(jù)庫更新操作,缺點(diǎn)是每次更新前都要進(jìn)行1次查詢操作。

而對于這里的更新FaceUrl與AvatarUrl的應(yīng)用場景,更新前就明確知道數(shù)據(jù)已經(jīng)改變,直接更新數(shù)據(jù)庫即可。ef change tracking的更新前查詢不僅沒有必要,而且增加了額外的開銷。

于是,嘗試尋找新的解決方法。

開始嘗試的是EF的DbEntityEntry,未抽象的實(shí)現(xiàn)代碼:

public class EfUnitOfWork : DbContext, IUnitOfWork
{
public async Task UpdateAsync(User user)
{
base.Set().Attach(user);
base.Entry(user).Property(x => x.FaceUrl).IsModified = true;
base.Entry(user).Property(x => x.AvatarUrl).IsModified = true;
return (await base.SaveChangesAsync()) > 0;
}
}

用代碼:

await UpdateAsync(new User { UserId = userId, FaceUrl = faceUrl, AvatarUrl = avatarUrl });

但是基于這個實(shí)現(xiàn),很難抽象出一個好用的接口方法。

后來突然想到前一段時間在一個項(xiàng)目中用到的EntityFramework.Extended。針對Update操作,它實(shí)現(xiàn)了一個優(yōu)雅的EF擴(kuò)展,為何不直接用它呢?

//example of using an IQueryable as the filter for the updatevar users = context.Users.Where(u => u.FirstName == "firstname");
context.Users.Update(users, u => new User {FirstName = "newfirstname"});

于是,如獲珍寶地基于EntityFramework.Extended進(jìn)行實(shí)現(xiàn)。

首先在IUnitOfWork中添加一個UpdateAsync()的接口方法:

public interface IUnitOfWork : IDisposable
{
    Task UpdateAsync(IQueryable source, Expression> updateExpression) where T : class;
}

然后在IUnitOfWork.UpdateAsync()的實(shí)現(xiàn)中,調(diào)用EntityFramework.Extended的UpdateAsync擴(kuò)展方法,完成Update操作:

using EntityFramework.Extensions;
public class EfUnitOfWork : DbContext, IUnitOfWork
{
async Task IUnitOfWork.UpdateAsync(IQueryable source,
Expression> updateExpression)
{
return (await source.UpdateAsync(updateExpression)) > 0;
}
}

隨之,Application.Services中的實(shí)現(xiàn)代碼改為這樣:

public async Task UpdateFaceAvatar(Guid userId, string faceUrl, string avatarUrl)
{
IQueryable userQuery = _userRepository.GetByUserId(userId);
return await _unitOfWork.UpdateAsync(
userQuery,
x => new User { FaceUrl = faceUrl, AvatarUrl = avatarUrl }
);
}

(注:這里的_userRepository.GetByUserId的返回類型需要改為IQueryable,再一次驗(yàn)證了Repository返回IQueryable的必要性,相關(guān)博文:開發(fā)筆記:用不用UnitOfWork以及Repository返回什么集合類型)

跑單元測試驗(yàn)證一下。

單元測試代碼:

[Fact]
public async Task UpdateFaceAvatar()
{
var result = await _userService.UpdateFaceAvatar(userId, faceUrl, avatarUrl);
Assert.True(result);
}

試結(jié)果:

1 passed, 0 failed, 0 skipped, took 11.38 seconds (xUnit.net 1.9.1 build 1600).

測試通過!

用SQL Profiler查看一下數(shù)據(jù)庫中實(shí)際執(zhí)行的SQL語句:

exec sp_executesql N'UPDATE [dbo].[Users] SET
[FaceUrl] = @p__update__0,
[AvatarUrl] = @p__update__1
FROM [dbo].[Users] AS j0 INNER JOIN (
SELECT
AS [C1],
[Extent1].[UserId] AS [UserId]
FROM [dbo].[Users] AS [Extent1]
WHERE [Extent1].[UserId] = @p__linq__0
) AS j1 ON (j0.[UserId] = j1.[UserId])',N'@p__linq__0 uniqueidentifier,@p__update__0 nvarchar(24),@p__update__1 nvarchar(24)',
@p__linq__0='BD42420B-63CF-DD11-9E4D-001CF0CD104B',@p__update__0=N'20150810180742.png',@p__update__1=N'20150810180743.png'

就是我們期望的SQL語句。

最終驗(yàn)證了,添加IUnitOfWork.UpadteAsync()接口,基于EntityFramework.Extended,用EF實(shí)現(xiàn)數(shù)據(jù)庫中指定字段的更新,這種方法在實(shí)際開發(fā)中使用完全可行。

于是,又少了一個使用存儲過程的理由。

看完上述內(nèi)容,你們掌握EntityFramework.Extended如何用EF實(shí)現(xiàn)指定字段的更新的方法了嗎?如果還想學(xué)到更多技能或想了解更多相關(guān)內(nèi)容,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!


本文題目:EntityFramework.Extended如何用EF實(shí)現(xiàn)指定字段的更新
文章地址:http://m.jcarcd.cn/article/pdcsdj.html
主站蜘蛛池模板: 91午夜视 | 日本一本在线播放 | 日本看片一卡 | 欧美日韩国产一区二 | 成人淫色午夜福利 | 岛国大片在线一 | 日本高清视频免 | 国产精品盗摄视频 | 91精品一区福利 | 久在线观看免 | 国产乱伦亚洲精品 | 午夜国产精品理论 | 精品国产自在在线 | 91福利电影网 | 日本丰满b | 91精品午夜在线 | 日韩天天精品综合 | 日本成人精品 | 日本高清在线播放 | 精品视频在线三区 | 国产精品永久 | 国产老熟女网站 | 国偷自产婷婷 | 制服丝袜诱惑在线 | 91李宗精品72集 | 91电影福利| 国产在线播放不卡 | 国产精选线路一 | 人成视频播放 | 国产视频综合 | 91欧美精品 | 欧美综合专区 | 老女人丨91丨九色 | 91直播| 精品欧洲在线观看 | 国产高清激情视频 | 日韩成人免费 | 午夜福利区一区二区 | 国产韩日欧美在线 | 国产免费观看视频 | 成人午夜资料库 |