我正在开发一个 ASP.NET 网站项目。它没有非常一致的数据层,因此我尝试实现代码优先 Entity Framework 。
我最近发现制作 Entity Framework 的人创建了一个可与 Entity Framework 6 一起使用的新版本 EntityDataSource。
这个新数据源看起来非常好并且它更新了数据库。但它似乎没有调用我的 DbContext 类上的任何方法。
作为一些基本更改跟踪要求的一部分,我重写了 DbContext SaveChanges() 方法并放入一些代码来更新每个记录上的跟踪字段(CreatedBy、CreatedDate、ModifiedBy、ModifiedDate)。奇怪的是,当我直接使用 DBContect 时,会调用 SaveChanges() 方法。但是当我使用这个 EntityDataSource 时,它不会调用 SaveChanges()。
上面的 Entity Framework EntityDataSource如何更新数据库集?
有什么方法可以让这个 EntityDataSource 调用 DbContext SaveChanges() 方法吗?
是否有替代方法可以覆盖 DBContext SaveChanges 方法?
这是我的 Entity Framework 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 来访问 Applicants 的 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
最佳答案
上面的 Entity Framework EntityDataSource如何更新数据库集?
EntityDataSource 使用底层 ObjectContext ,而不是 DbContext。这就是为什么您永远不会看到任何内容直接通过 DbContext 上的 SaveChanges()
重载。
有什么方法可以让这个 EntityDataSource 调用 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();
}
是否有替代方法来重写 DBContext SaveChanges 方法?
仅是我上面描述的内容。您可以挂接到 ObjectContext
并获取传递的事件,但当 context is created 时您需要它的实例。 (参见该事件)。然后您可以订阅SavingChanges事件作为您的 Hook ,尽管这比 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
<小时/>
关于asp.net - Entity Framework 6 EntityDataSource 未在 DbContext 中调用 SaveChanges,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33435588/