“附加或添加不是新的实体...从另一个 DataContext 加载。这是不支持的。”插入链接器对象时出现问题

发布于 2024-08-31 04:35:33 字数 4201 浏览 0 评论 0原文

与其他问题类似的错误,但不完全相同,我不想附加任何内容。

我想做的是将新行插入到链接表中,特别是 UserAccomplishment 中。关系在 LINQ to User 和 Accomplishment 表中设置。

我有一个通用插入函数:

Public Function insertRow(ByVal entity As ImplementationType) As Boolean
        If entity IsNot Nothing Then

            Dim lcfdatacontext As New LCFDataContext()
            Try
                lcfdatacontext.GetTable(Of ImplementationType)().InsertOnSubmit(entity)

                lcfdatacontext.SubmitChanges()
                lcfdatacontext.Dispose()
                Return True
            Catch ex As Exception
                Return False
            End Try
        Else
            Return False
        End If
End Function

如果您尝试为 UserAccomplishment 提供两个适当的对象,如果 User 或 Accomplishment 已经存在,这自然会失败。它仅在用户和成就都不存在时才有效。我预料到了这种行为。有效的方法是简单地为 userAccomplishment 对象提供 user.id 和 Achievement.id 并填充其余字段。这可行,但在我的应用程序中使用起来有点尴尬,简单地传入两个对象并让它计算出已经存在的和不存在的会容易得多。好的,所以我做了以下操作(请忽略这个效率非常低的事实,因为我知道它是这样):

Public Class UserAccomplishmentDao
    Inherits EntityDao(Of UserAccomplishment)

    Public Function insertLinkerObjectRow(ByVal userAccomplishment As UserAccomplishment)

        Dim insertSuccess As Boolean = False

        If Not userAccomplishment Is Nothing Then

            Dim userDao As New UserDao()
            Dim accomplishmentDao As New AccomplishmentDao()
            Dim user As New User()
            Dim accomplishment As New Accomplishment()


            'see if either object already exists in db'
            user = userDao.getOneByValueOfProperty("Id", userAccomplishment.User.Id)
            accomplishment = accomplishmentDao.getOneByValueOfProperty("Id", userAccomplishment.Accomplishment.Id)


            If user Is Nothing And accomplishment Is Nothing Then
                'neither the user or the accomplishment exist, both are new so insert them both, typical insert'
                insertSuccess = Me.insertRow(userAccomplishment)

            ElseIf user Is Nothing And Not accomplishment Is Nothing Then
                'user is new, accomplishment is not new, so just insert the user, and the relation in userAccomplishment'
                Dim userWithExistingAccomplishment As New UserAccomplishment(userAccomplishment.User, userAccomplishment.Accomplishment.Id, userAccomplishment.LastUpdatedBy)
                insertSuccess = Me.insertRow(userWithExistingAccomplishment)
            ElseIf Not user Is Nothing And accomplishment Is Nothing Then
                'user is not new, accomplishment is new, so just insert the accomplishment, and the relation in userAccomplishment'
                Dim existingUserWithAccomplishment As New UserAccomplishment(userAccomplishment.UserId, userAccomplishment.Accomplishment, userAccomplishment.LastUpdatedBy)
                insertSuccess = Me.insertRow(existingUserWithAccomplishment)
            Else
                'both are not new, just add the relation'
                Dim userAccomplishmentBothExist As New UserAccomplishment(userAccomplishment.User.Id, userAccomplishment.Accomplishment.Id, userAccomplishment.LastUpdatedBy)
                insertSuccess = Me.insertRow(userAccomplishmentBothExist)
            End If

        End If

        Return insertSuccess

    End Function

End Class

好吧,在这里我基本上检查提供的用户和成就是否已存在于数据库中,如果存在,则调用一个适当的构造函数将已存在的内容保留为空,但提供其余信息以便插入成功。

但是,在尝试插入时:

Dim result As Boolean = Me.userAccomplishmentDao.insertLinkerObjectRow(userAccomplishment)

其中用户已经存在,但成就不存在(99% 的典型情况),我收到错误:

"An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext. This is not supported."

我现在已经多次调试此问题,并且不确定为什么会发生这种情况,如果用户或成就存在,我没有将其包含在尝试插入的最终对象中。因此似乎没有尝试添加任何内容。即使在调试中,在插入时,该对象也被设置为空。所以成就是新的,用户是空的。

1)为什么它仍然这么说,我该如何修复它..使用我当前的结构

2)先发制人的“使用存储库模式答案” - 我知道这种方式通常很糟糕,我应该使用存储库模式。但是,我无法在当前项目中使用它,因为由于我不存在知识和时间限制,我没有时间重构它。该应用程序的使用量将会如此之小,以至于数据上下文的低效使用以及您所拥有的内容不再那么重要。一旦它启动并运行,我就可以对其进行重构,但现在我只需要“推进”我当前的结构。

编辑:我也刚刚在两者都存在时测试了这一点,并且仅将每个对象的 ID 插入到表中,这有效。所以我想我可以手动插入不存在的对象作为单个插入,然后仅将 id 放入链接表中,但我仍然不知道为什么当一个对象存在时,我将其设为空,它确实如此不工作。

Similar error as other questions, but not quite the same, I am not trying to attach anything.

What I am trying to do is insert a new row into a linking table, specifically UserAccomplishment. Relations are set in LINQ to User and Accomplishment Tables.

I have a generic insert function:

Public Function insertRow(ByVal entity As ImplementationType) As Boolean
        If entity IsNot Nothing Then

            Dim lcfdatacontext As New LCFDataContext()
            Try
                lcfdatacontext.GetTable(Of ImplementationType)().InsertOnSubmit(entity)

                lcfdatacontext.SubmitChanges()
                lcfdatacontext.Dispose()
                Return True
            Catch ex As Exception
                Return False
            End Try
        Else
            Return False
        End If
End Function

If you try and give UserAccomplishment the two appropriate objects this will naturally crap out if either the User or Accomplishment already exist. It only works when both user and accomplishment don't exist. I expected this behavior. What does work is simply giving the userAccomplishment object a user.id and accomplishment.id and populating the rest of the fields. This works but is kind of awkward to use in my app, it would be much easier to simply pass in both objects and have it work out what already exists and what doesn't. Okay so I made the following (please ignore the fact that this is horribly inefficient because I know it is):

Public Class UserAccomplishmentDao
    Inherits EntityDao(Of UserAccomplishment)

    Public Function insertLinkerObjectRow(ByVal userAccomplishment As UserAccomplishment)

        Dim insertSuccess As Boolean = False

        If Not userAccomplishment Is Nothing Then

            Dim userDao As New UserDao()
            Dim accomplishmentDao As New AccomplishmentDao()
            Dim user As New User()
            Dim accomplishment As New Accomplishment()


            'see if either object already exists in db'
            user = userDao.getOneByValueOfProperty("Id", userAccomplishment.User.Id)
            accomplishment = accomplishmentDao.getOneByValueOfProperty("Id", userAccomplishment.Accomplishment.Id)


            If user Is Nothing And accomplishment Is Nothing Then
                'neither the user or the accomplishment exist, both are new so insert them both, typical insert'
                insertSuccess = Me.insertRow(userAccomplishment)

            ElseIf user Is Nothing And Not accomplishment Is Nothing Then
                'user is new, accomplishment is not new, so just insert the user, and the relation in userAccomplishment'
                Dim userWithExistingAccomplishment As New UserAccomplishment(userAccomplishment.User, userAccomplishment.Accomplishment.Id, userAccomplishment.LastUpdatedBy)
                insertSuccess = Me.insertRow(userWithExistingAccomplishment)
            ElseIf Not user Is Nothing And accomplishment Is Nothing Then
                'user is not new, accomplishment is new, so just insert the accomplishment, and the relation in userAccomplishment'
                Dim existingUserWithAccomplishment As New UserAccomplishment(userAccomplishment.UserId, userAccomplishment.Accomplishment, userAccomplishment.LastUpdatedBy)
                insertSuccess = Me.insertRow(existingUserWithAccomplishment)
            Else
                'both are not new, just add the relation'
                Dim userAccomplishmentBothExist As New UserAccomplishment(userAccomplishment.User.Id, userAccomplishment.Accomplishment.Id, userAccomplishment.LastUpdatedBy)
                insertSuccess = Me.insertRow(userAccomplishmentBothExist)
            End If

        End If

        Return insertSuccess

    End Function

End Class

Alright, here I basically check if the supplied user and accomplishment already exists in the db, and if so call an appropriate constructor that will leave whatever already exists empty, but supply the rest of the information so the insert can succeed.

However, upon trying an insert:

Dim result As Boolean = Me.userAccomplishmentDao.insertLinkerObjectRow(userAccomplishment)

In which the user already exists, but the accomplishment does not (the 99% typical scenario) I get the error:

"An attempt has been made to Attach or Add an entity that is not new, perhaps having been loaded from another DataContext. This is not supported."

I have debugged this multiple times now and am not sure why this is occuring, if either User or Accomplishment exist, I am not including it in the final object to try to insert. So nothing appears to be attempted to be added. Even in debug, upon insert, the object was set to empty. So the accomplishment is new and the user is empty.

1) Why is it still saying that and how can I fix it ..using my current structure

2) Pre-emptive 'use repository pattern answers' - I know this way kind of sucks in general and I should be using the repository pattern. However, I can't use that in the current project because I don't have time to refactor that due to my non existence knowledge of it and time constraints. The usage of the app is going to so small that the inefficient use of datacontext's and what have you won't matter so much. I can refactor it once it's up and running, but for now I just need to 'push through' with my current structure.

Edit: I also just tested this when having both already exists, and only insert each object's IDs into the table, that works. So I guess I could manually insert whichever object doesn't exist as a single insert, then put the ids only into the linking table, but I still don't know why when one object exists, and I make it empty, it doens't work.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

蓝眼睛不忧郁 2024-09-07 04:35:33

首先,我认为你工作得太辛苦了,但这是可以理解的。

让我看看是否明白您要做什么:您想要更新跟踪用户和成就的关联表。无论预先存在什么,当您完成时,您都需要一个有效的 UserAccomplishment 记录,其中包含已履行且有效的关系。让我们开始:

public void AddUserAccomplishment(user User, accomplishment Accomplishment)
{
    using (LCFDataContext dc = new LCFDataContext())
    {
        // Substitute <UserName> for any other unique field in the record.
        var tempUser = dc.Users
            .Where(a => a.UserName.ToLower() == user.UserName.ToLower())
            .SingleOrDefault();

        // Using SingleOrDefault() creates an empty User entity object if 
        // a matching record can't be found, which means the Id field will
        // be equal to zero.
        if (tempUser.Id == 0)
        {
            // Populate the empty tempUser entity object
            tempUser.UserName = user.UserName;
               .
               .
               .
            dc.Users.InsertOnSubmit(tempUser);
        }

        // Do the same thing for the Accomplishment.
        var tempAccomplishment = dc.Accomplishments
            .Where(a => a.Title.ToLower() == accomplishment.Title.ToLower())
            .SingleOrDefault();

        if (tempAccomplishment.Id == 0)
        {
            // Populate the empty tempAccomplishment entity object
            tempAccomplishment.Title = accomplishment.Title;
               .
               .
               .
            dc.Accomplishments.InsertOnSubmit(tempAccomplishment);
        }

        // Now, you need to make sure that the UserAccomplishment entity object
        // doesn't already exist.
        if (dc.UserAccomplishments
            .Where(a => a.User.Id == tempUser.Id
                && a.Accomplishment.Id == tempAccomplishment.Id)
            .Count == 0)
        {
            UserAccomplishment userAccomplishment = new UserAccomplishment();

            userAccomplishment.User = tempUser;
            userAccomplishment.Accomplishment = tempAccomplishment;
            dc.UserAccomplishments.InsertOnSubmit(userAccomplishment);
        }
        else
        {
            // The UserAccomplishment record already exists, so throw an
            // exception or display an error message.
        }

        dc.SubmitChanges();       
    }
}

让我知道这是否有帮助......

First and foremost, I think you're working too hard, but it's understandable.

Let me see if understand what you're trying to do: You want to update an association table that tracks Users and Accomplishments. Regardless of what exists beforehand, by the time you are finished, you want a valid UserAccomplishment record, complete with fulfilled and valid relations. Let's start with:

public void AddUserAccomplishment(user User, accomplishment Accomplishment)
{
    using (LCFDataContext dc = new LCFDataContext())
    {
        // Substitute <UserName> for any other unique field in the record.
        var tempUser = dc.Users
            .Where(a => a.UserName.ToLower() == user.UserName.ToLower())
            .SingleOrDefault();

        // Using SingleOrDefault() creates an empty User entity object if 
        // a matching record can't be found, which means the Id field will
        // be equal to zero.
        if (tempUser.Id == 0)
        {
            // Populate the empty tempUser entity object
            tempUser.UserName = user.UserName;
               .
               .
               .
            dc.Users.InsertOnSubmit(tempUser);
        }

        // Do the same thing for the Accomplishment.
        var tempAccomplishment = dc.Accomplishments
            .Where(a => a.Title.ToLower() == accomplishment.Title.ToLower())
            .SingleOrDefault();

        if (tempAccomplishment.Id == 0)
        {
            // Populate the empty tempAccomplishment entity object
            tempAccomplishment.Title = accomplishment.Title;
               .
               .
               .
            dc.Accomplishments.InsertOnSubmit(tempAccomplishment);
        }

        // Now, you need to make sure that the UserAccomplishment entity object
        // doesn't already exist.
        if (dc.UserAccomplishments
            .Where(a => a.User.Id == tempUser.Id
                && a.Accomplishment.Id == tempAccomplishment.Id)
            .Count == 0)
        {
            UserAccomplishment userAccomplishment = new UserAccomplishment();

            userAccomplishment.User = tempUser;
            userAccomplishment.Accomplishment = tempAccomplishment;
            dc.UserAccomplishments.InsertOnSubmit(userAccomplishment);
        }
        else
        {
            // The UserAccomplishment record already exists, so throw an
            // exception or display an error message.
        }

        dc.SubmitChanges();       
    }
}

Let me know if this helps...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文