EF 4.3 と移行を使用した ASP.NET MVC 4 アプリケーションがあります。WebGrid ヘルパーを使用して、システム ユーザーの詳細を表示します。
@grid.GetHtml(
headerStyle: "gridHeader",
footerStyle: "gridFooter",
firstText: "<< First",
previousText: "< Previous",
nextText: "Next >",
lastText: "Last >>",
alternatingRowStyle: "gridAlternativeRow",
columns: new[] {
grid.Column("Login", header: "User Login", canSort: true),
grid.Column("FullName", header: "User Name", canSort: true),
grid.Column("Email", header: "User Email", canSort: true),
grid.Column("Category", header: "User Category", canSort: true),
grid.Column(
"",
header: "",
format: @<text>
@Html.ActionLink("Edit", "Edit", new { id=item.Id} )
</text>
)
})
ご覧のとおり、Edit アクション メソッドは、ユーザーの詳細を編集する役割を果たします。これは、View Model をビューに渡す方法です。
public ActionResult Edit(int Id)
{
User user = repo.GetUser(Id);
RegisterModel rm = new RegisterModel();
rm.Id = user.Id;
rm.Name = user.FullName;
rm.UserName = user.Login;
rm.Email = user.Email;
rm.UserCategory = user.Category;
rm.Categories = new List<SelectListItem>();
List<Category> categories = repo.GetAllCategories();
foreach (var item in categories)
{
SelectListItem sli = new SelectListItem();
sli.Value = null;
sli.Text = item.Title;
if (user.Category == item.Title) sli.Selected = true;
rm.Categories.Add(sli);
}
return View(rm);
}
そして、これが詳細を保存する方法です:
[HttpPost]
public ActionResult Edit(RegisterModel rm, string NewPassword, string OldLogin)
{
if (NewPassword != "")
{
var token = WebSecurity.GeneratePasswordResetToken(OldLogin);
WebSecurity.ResetPassword(token, NewPassword);
}
User user = new User();
user.Id = Convert.ToInt32(rm.Id);
user.FullName = rm.Name;
user.Email = rm.Email;
user.Category = rm.UserCategory;
user.Login = rm.UserName;
string result = repo.UpdateUserDetails(user);
return RedirectToAction("Index");
}
次に、ユーザーのリストをソースとする Index アクション メソッドにリダイレクトし、それを WebGrid ヘルパーを使用してビューに戻します。
リポジトリにアクセスするたびに、DbContext オブジェクトからユーザーの最新の値を取得します。
public List<User> GetAllUsersWithoutAdmin()
{
return context.Users.Where(x => x.Id != 1).OrderBy(x => x.FullName).ToList();
}
public User GetUser(int userId)
{
return context.Users.FirstOrDefault(x => x.Id == userId);
}
public string UpdateUserDetails(User user)
{
string info;
try
{
User uUser = context.Users.FirstOrDefault(x => x.Id == user.Id);
uUser.Category = user.Category;
uUser.Email = user.Email;
uUser.FullName = user.FullName;
uUser.Login = user.Login;
context.SaveChanges();
info = "success";
}
catch (Exception err)
{
info = err.Message;
}
return info;
}
また、UoW パターンを使用して、同じコントローラーで異なるリポジトリを使用する問題を解決します。
public interface IUnitOfWork
{
int SaveChanges();
}
次に、各リポジトリは次のインターフェースを実装します。
private ActivityLogContext context;
public UserRepository(IUnitOfWork _context)
{
context = _context as ActivityLogContext;
}
AddBindings() メソッドによって Ninject Controller Factory に実装されているスレッドのスコープ内の同じコンテキストで共有します。
private void AddBindings()
{
ninjectKernel.Bind<IActivityRepository>().To<ActivityRepository>();
ninjectKernel.Bind<IUserRepository>().To<UserRepository>();
ninjectKernel.Bind<ICategoryRepository>().To<CategoryRepository>();
ninjectKernel.Bind<IUnitOfWork>().To<ActivityLogContext>().InThreadScope();
}
問題: 奇妙な理由により、ユーザー オブジェクトが編集されているときに、コンテキスト オブジェクトがユーザー プロパティに対して間違った値を表示することがよくあります。DbContext と実際のデータの間のどこかで EF のレベルで発生しています。特に、SQL サーバーのそのデータは常に正しいです。EF がプロパティの以前の値をキャッシュしているように見え、データベースから取得する代わりにそれらを取得します。この動作が正確にいつ発生するかは観察していませんが、かなり頻繁に発生します。オブジェクトが編集されるたびに 2 回または 3 回発生します。場合によっては、連続して数回発生することもあります。
以前のアプリケーションで同じ設定を使用しましたが、すべて問題ありませんでした。今回の唯一の違いは、私が WebGrid Helper を使用していることと、WebGrid Helper を使用するページだけが私のアプリケーションでこの問題を引き起こしているように見えることです???