我正在开发一个asp.net网站项目。它没有非常一致的数据层,所以我试图实现代码第一实体框架。
我最近发现创建实体框架的人创建了一个与Entity Framework 6一起使用的新版EntityDataSource。
这个新的数据源似乎非常好,它会更新数据库。它似乎没有调用我的DbContext类上的任何方法。
作为一些基本的变更跟踪要求的一部分,我重写了DbContext SaveChanges()方法并添加了一些代码来更新每条记录(CreatedBy,CreatedDate,ModifiedBy,ModifiedDate)的跟踪字段。奇怪的是,当我直接使用DBContect时,会调用SaveChanges()方法。但是当我使用这个EntityDataSource时,它不会调用SaveChanges()。
上面的Entity Framework EntityDataSource如何更新dbsets?
有什么办法可以让这个EntityDataSource调用DbContext SaveChanges()方法吗?
是否有替代覆盖DBContext SaveChanges方法的方法?
以下是我的实体框架EntityDataSource控件定义
的示例<asp:ListView ID="FormView" runat="server" DataKeyNames="RecordId" DataSourceID="ApplicantDataSource" DefaultMode="Edit">
<EditItemTemplate>
<asp:TextBox runat="server" ID="SomeField" Text='<%# Bind("SomeField")%>' ></asp:TextBox>
</EditItemTemplate>
</asp:ListView>
<ef:EntityDataSource runat="server"
ID="ApplicantDataSource"
ContextTypeName="Organisation.Application.MyDbContext"
EntitySetName="Applicants"
Where="it.RecordId=@RecordId"
EnableUpdate="true">
<WhereParameters>
<asp:QueryStringParameter Name="RecordId" QueryStringField="RecordId" DbType="String" DefaultValue=""/>
</WhereParameters>
</ef:EntityDataSource>
这是我的DbContext(减少)。在EntityDataSource上调用update时,它不会通过SaveChanges()。它甚至没有调用Applicants属性中的getter来访问申请人的DBSet。它仍然设法以某种方式保存信息!
Public Class MyDbContext
Inherits DbContext
Public Shared Sub MyDbContext()
Database.SetInitializer(Of MyDbContext)(Nothing)
End Sub
Public Sub New()
MyBase.New("Name=ConnectionString")
End Sub
Public Property Applicants() As DbSet(Of Applicant)
Protected Overrides Sub OnModelCreating(modelBuilder As DbModelBuilder)
modelBuilder.Conventions.Remove(Of PluralizingTableNameConvention)()
MyBase.OnModelCreating(modelBuilder)
End Sub
Public Overrides Function SaveChanges() As Integer
Try
Dim entities = Me.ChangeTracker.Entries().Where(Function(x) TypeOf x.Entity Is MyBase AndAlso (x.State = EntityState.Added OrElse x.State = EntityState.Modified))
Dim currentUsername As String
If HttpContext.Current IsNot Nothing And HttpContext.Current.User IsNot Nothing Then
currentUsername = HttpContext.Current.User.Identity.Name
Else
currentUsername = "System"
End If
For Each entity In entities
If entity.State = EntityState.Added Then
DirectCast(entity.Entity, MyBase).CreatedDate = DateTime.Now
DirectCast(entity.Entity, MyBase).CreatedBy = currentUsername
ElseIf entity.State = EntityState.Modified Then
entity.Property("CreatedBy").IsModified = False
entity.Property("CreatedDate").IsModified = False
End If
DirectCast(entity.Entity, MyBase).ModifiedDate = DateTime.Now
DirectCast(entity.Entity, MyBase).ModifiedBy = currentUsername
Next
Return MyBase.SaveChanges()
Catch ex As DbEntityValidationException
' Retrieve the error messages as a list of strings.
Dim errorMessages = ex.EntityValidationErrors.SelectMany(Function(x) x.ValidationErrors).[Select](Function(x) x.ErrorMessage)
' Join the list to a single string.
Dim fullErrorMessage = String.Join("; ", errorMessages)
' Combine the original exception message with the new one.
Dim exceptionMessage = String.Concat(ex.Message, " The validation errors are: ", fullErrorMessage)
' Throw a new DbEntityValidationException with the improved exception message.
Throw New DbEntityValidationException(exceptionMessage, ex.EntityValidationErrors)
End Try
End Function
End Class
答案 0 :(得分:1)
EntityDataSource使用底层ObjectContext,而不是DbContext。这就是为什么你从来没有看到任何东西直接通过你的DbContext上的SaveChanges()
重载。
是和否,您可以重载Updating
方法,然后EntityDataSourceChangingEventArgs
可以访问DbContext,然后调用它。这对于你的所有视图都是必要的,但我没有看到一种方法可以轻松地集中这个及其糟糕的设计(因此没有)。
protected void x_Updating(object sender, EntityDataSourceChangingEventArgs e) {
e.Cancel = true;
DbContext dbc = new DbContext(e.Context, true);
new YourDbContext(dbc).SaveChanges();
}
只有我上面描述的内容。您可以挂钩到ObjectContext
并获取传递的事件,但是在context is created时需要它的实例(请参阅该事件)。然后,您可以订阅SavingChanges事件作为您的钩子,尽管这比DbContext上的SaveChanges
更有限。如果你想做的就是
下面是一个Vb.Net代码示例。如果语法关闭,请不要开枪,因为我在Vb中写了任何东西已经很久了。您可能需要在设计器中注册onContextCreated
(aspx代码)。
免责声明 - 我没有测试下面的代码。它部分基于您的代码和SavingChanges文档中的示例代码。
Protected Sub onContextCreated(ByVal sender As Object, ByVal args As EntityDataSourceContextCreatedEventArgs)
AddHandler args.Context.SavingChanges, AddressOf context_SavingChanges
End Sub
Private Sub context_SavingChanges(ByVal sender As Object, ByVal e As EventArgs)
Dim context As ObjectContext = TryCast(sender, ObjectContext)
If context IsNot Nothing Then
If HttpContext.Current IsNot Nothing And HttpContext.Current.User IsNot Nothing Then
currentUsername = HttpContext.Current.User.Identity.Name
Else
currentUsername = "System"
End If
For Each entity As ObjectStateEntry In context.ObjectStateManager.GetObjectStateEntries(EntityState.Added Or EntityState.Modified)
If entity.State = EntityState.Added Then
DirectCast(entity.Entity, MyBase).CreatedDate = DateTime.Now
DirectCast(entity.Entity, MyBase).CreatedBy = currentUsername
ElseIf entity.State = EntityState.Modified Then
entity.Property("CreatedBy").IsModified = False
entity.Property("CreatedDate").IsModified = False
End If
DirectCast(entity.Entity, MyBase).ModifiedDate = DateTime.Now
DirectCast(entity.Entity, MyBase).ModifiedBy = currentUsername
Next
End If
End Sub