C# 在web app中使用实体框架检索和更新记录
我是开发新手,尝试使用Entity Framework 5.0(数据库优先方法)在ASP.NET web应用程序页面的FormView中检索要显示和编辑的记录,但我不确定最好的方法 要检索记录,我使用以下代码:C# 在web app中使用实体框架检索和更新记录,c#,asp.net,entity-framework,linq-to-entities,C#,Asp.net,Entity Framework,Linq To Entities,我是开发新手,尝试使用Entity Framework 5.0(数据库优先方法)在ASP.NET web应用程序页面的FormView中检索要显示和编辑的记录,但我不确定最好的方法 要检索记录,我使用以下代码: protected void Page_Load(object sender, EventArgs e) { LoadData(int.Parse(Session["PersonID"].ToString())); } private void LoadData(int iPe
protected void Page_Load(object sender, EventArgs e)
{
LoadData(int.Parse(Session["PersonID"].ToString()));
}
private void LoadData(int iPersonID)
{
using (PeopleEntities ctx = new PeopleEntities())
{
var query = (from a in ctx.People
where a.PersonID == iPersonID
select a).FirstOrDefault();
TextBoxFirstName.Text = query.FirstName;
TextBoxLastName.Text = query.LastName;
}
}
为了保存它,我使用:
protected void ButtonSave_Click(object sender, EventArgs e)
{
SaveEmployee(int.Parse(Session["PersonID"].ToString()));
}
private void SaveEmployee(int iPersonID = 0)
{
using (PeopleEntities ctx = new PeopleEntities())
{
var query = (from a in ctx.People
where a.PersonID == iPersonID
select a).FirstOrDefault();
query.FirstName = TextBoxFirstName.Text;
query.LastName = TextBoxLastName.Text;
ctx.SaveChanges();
}
}
让这两种方法分别查询数据库以检索和更新记录对我来说似乎很愚蠢,但是,同样,我是一个新手,也许我只是缺少了一些东西。是否有一种方法可以使用实体填充FormView上的控件,并且有一种方法可以保存记录,而不必根据状态手动分配值(query.FirstName=TextBoxFirstName.Text等)
我已经看过EntityDataSource,但我认为除了最简单的东西之外,这不是一个好的选择
有没有人能告诉我我现在做的是否合适,或者提供一个更好的例子或指导
非常感谢你的帮助 我也是这样做的。有必要检索您希望更新的对象。我也是这样做的。有必要检索您希望更新的对象。最好的方法是,IMHO,当您仅检索要显示的数据时,不进行更改跟踪。这将避免性能问题。因此,使用
AsNoTracking
方法来避免更改跟踪代理
然后,对于更新,您应该在启用更改跟踪的情况下加载,这就是为什么在保存部件上没有调用AsNoTracking
记住检查空值。您使用的是FirstOrDefault,但由于您使用的是主键,因此不会有第二条记录,所以只需使用SingleOrDefault即可。但由于默认值(null)可能发生,请检查null值
另外,使用lambda表达式。它们一开始并不容易使用,但您只需稍加努力就可以使用,而且它们将大大简化您的代码
但是从你的问题来看,有一些解决方法可以避免这种情况,但它们不是最好的方法。您应该避免使用长寿命实体,而更喜欢长寿命对象的ViewModels,并考虑到存储库和持久实体的UnitOfWork模式
如果您真的需要,您可以从上下文中分离
您的实体,在任何地方使用它,并且当您准备好时,将其附加回去,并将其状态设置为已修改
。
为此,请看这里:
就你的情况而言,我建议:
private void LoadData(int iPersonID)
{
using (PeopleEntities ctx = new PeopleEntities())
{
// AsNoTracking will avoid performance hit of change-tracking here...
// Since we're building-up a view, not an update case yet, you don't have to create
// proxies that will check for entity changing...
var query = ctx.People.AsNoTracking().SingleOrDefault(_people => _people.PersonID == iPersonID)
// Rendering comes into action
if (query != null)
{
TextBoxFirstName.Text = query.FirstName;
TextBoxLastName.Text = query.LastName;
}
}
}
private void SaveEmployee(int iPersonID = 0)
{
using (PeopleEntities ctx = new PeopleEntities())
{
var query = ctx.Prople.SingleOrDefault(_person => _person.PersonID == iPersonID);
if (query != null)
{
query.FirstName = TextBoxFirstName.Text;
query.LastName = TextBoxLastName.Text;
ctx.SaveChanges();
}
}
}
最好的方法是,IMHO,当您检索只显示的数据时,不进行更改跟踪。这将避免性能问题。因此,使用AsNoTracking
方法来避免更改跟踪代理
然后,对于更新,您应该在启用更改跟踪的情况下加载,这就是为什么在保存部件上没有调用AsNoTracking
记住检查空值。您使用的是FirstOrDefault,但由于您使用的是主键,因此不会有第二条记录,所以只需使用SingleOrDefault即可。但由于默认值(null)可能发生,请检查null值
另外,使用lambda表达式。它们一开始并不容易使用,但您只需稍加努力就可以使用,而且它们将大大简化您的代码
但是从你的问题来看,有一些解决方法可以避免这种情况,但它们不是最好的方法。您应该避免使用长寿命实体,而更喜欢长寿命对象的ViewModels,并考虑到存储库和持久实体的UnitOfWork模式
如果您真的需要,您可以从上下文中分离
您的实体,在任何地方使用它,并且当您准备好时,将其附加回去,并将其状态设置为已修改
。
为此,请看这里:
就你的情况而言,我建议:
private void LoadData(int iPersonID)
{
using (PeopleEntities ctx = new PeopleEntities())
{
// AsNoTracking will avoid performance hit of change-tracking here...
// Since we're building-up a view, not an update case yet, you don't have to create
// proxies that will check for entity changing...
var query = ctx.People.AsNoTracking().SingleOrDefault(_people => _people.PersonID == iPersonID)
// Rendering comes into action
if (query != null)
{
TextBoxFirstName.Text = query.FirstName;
TextBoxLastName.Text = query.LastName;
}
}
}
private void SaveEmployee(int iPersonID = 0)
{
using (PeopleEntities ctx = new PeopleEntities())
{
var query = ctx.Prople.SingleOrDefault(_person => _person.PersonID == iPersonID);
if (query != null)
{
query.FirstName = TextBoxFirstName.Text;
query.LastName = TextBoxLastName.Text;
ctx.SaveChanges();
}
}
}
“在我看来,让这两种方法分别查询数据库似乎很愚蠢
检索和更新记录“
你是绝对正确的,应该是一个你应该努力遵循的咒语原则
在这里,您选择在页面加载事件中检索数据,并在按钮单击事件中再次检索数据。这两个事件都发生在网页的同一实例中。您可以将其存储在实例变量中,并在单击按钮时重新使用它,或者您可以为“延迟加载”的实体设置属性。有各种各样的方法可以做到这一点。在这里,延迟加载可能无疑是过火了,因为您可能只会使用PageLoad中的属性。加载应该理解何时需要转到数据库,何时不需要
必须转到数据库以获取首次加载页面时要显示的数据。此后,当页面发回时,数据通常以表单值的形式出现
在更新记录时,也需要转到数据库,在本例中,当用户单击save按钮时会发生这种情况
下面是一个我可能不应该提到的延迟加载示例:
private People _Person;
//lazy loaded property
private People Person
{
get
{
if (_Person == null)
using (PeopleEntities ctx = new PeopleEntities())
_Person = GetPerson(ctx);
//returning a Person that isn't updateable because we've disposed of the context
return _Person;
}
}
//Retrieve an updateable person
private static object GetPerson(PeopleEntities ctx)
{
return (from a in ctx.People
where a.PersonID == int.Parse(Session["PersonID"]
select a).FirstOrDefault();
}
代码的另一个问题是,您总是根据数据库中的值设置PageLoad事件中的文本框。这意味着,当您进入按钮Save\u Click
事件时,回发的值已被数据库中的内容覆盖,更改将不会保存
所以你应该这样做:
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)//Only do this first time it's loaded
{
TextBoxFirstName.Text = Person.FirstName;
TextBoxLastName.Text = Person.LastName;
}
}
您单击的按钮可以如下所示:
protected void ButtonSave_Click(object sender, EventArgs e)
{
SavePerson(TextBoxFirstName.Text, TextBoxLastName.Text);
}
private SavePerson(string firstName, string lastName)
{
using (PeopleEntities ctx = new PeopleEntities())
{
var person = GetPerson(ctx);
person.FirstName = firstName;
person.LastName = lastName;
ctx.SaveChanges();
}
}
在编码过程中,您会发现您希望在其他页面上重复SavePerson
和GetPerson
代码。-这就是您开始引入存储库或层的时候。不要忘记你应该努力遵循的原则,并将代码移到另一个类中,这样你就可以重复使用它
该类应该位于PeopleRepository
或其他层中。最终,您会发现PeopleRepository
中的代码看起来很复杂
xxx.xxx.Select(c => new { c.FriendInvitationID,c.AccountSenderID,
c.Account1.AccountID, c.Account1.FirstName, c.Account1.LastName, c.Account1.Email,
c.FriendInvitationStatus, c.CreationDate })
.Where(c => c.AccountSenderID == userId_int).ToList();