加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

asp.net – 实体框架6 EntityDataSource不在DbContext中调用Save

发布时间:2020-12-16 09:41:45 所属栏目:asp.Net 来源:网络整理
导读:我正在开发一个asp.net网站项目.它没有非常一致的数据层,所以我试图实现代码第一实体框架. 我最近发现制作实体框架的人已经创建了一个与Entity Framework 6一起使用的新版EntityDataSource. http://blogs.msdn.com/b/webdev/archive/2014/02/28/announcing-t
我正在开发一个asp.net网站项目.它没有非常一致的数据层,所以我试图实现代码第一实体框架.

我最近发现制作实体框架的人已经创建了一个与Entity Framework 6一起使用的新版EntityDataSource.

http://blogs.msdn.com/b/webdev/archive/2014/02/28/announcing-the-release-of-dynamic-data-provider-and-entitydatasource-control-for-entity-framework-6.aspx

这个新的数据源似乎非常好,它更新了数据库.它似乎没有调用我的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

解决方法

上面的Entity Framework EntityDataSource如何更新dbsets?

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事件作为您的钩子,虽然这比DbContext上的SaveChanges更有限.如果你想做的就是

这是一个Vb.Net代码样本,可以用来挂钩.如果语法关闭,不要开枪,因为我在Vb中写了任何东西已经很久了.您可能需要在设计器(aspx代码)中注册onContextCreated.

免责声明 – 我没有测试下面的代码.它部分基于您的代码和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

部分答案的来源:http://w3stack.org/question/how-can-i-override-dbcontext-savechanges-when-using-entitydatasource-and-database-generated-model-edmx-ef-5/

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读