0

背景:我正在解析一个 XML 文件(图书签名事件信息),然后尝试通过 Entity Framework Code First(在 Entity Framework Power Tools Beta 3 的帮助下)基于 Parsed 数据创建数据库记录。

对解析逻辑进行排序后,我有以下代码用于将解析后的数据存储到数据库中:

using (var context = new BSContext())
{
    foreach (var e in events)
    {
        try
        {                    
            // Create the Author Entity
            var AuthorEntity = parser.getAuthorByName(e.Author);
            if (AuthorEntity == null)
            {
                AuthorEntity = new Author()
                {
                    Name = e.Author
                };
                context.Authors.Add(AuthorEntity);
                context.SaveChanges();
            }                        


            // Create the Location Entity
            var LocationEntity = parser.getLocationByNameAddressAndPostCode(e.Location.Name, e.Location.Address, e.Location.PostCode);
            if (LocationEntity == null)
            {
                LocationEntity = new Location()
                {
                    Name = e.Location.Name,
                    Address = e.Location.Address,
                    City = e.Location.City,
                    County = e.Location.County,
                    PostCode = e.Location.PostCode,
                    Telephone = e.Location.Telephone
                };
                context.Locations.Add(LocationEntity);
                context.SaveChanges();
            }                        


            // Create the Book Entity
            var BookEntity = parser.getBookByName(e.Book.Name);
            if(BookEntity == null)
            {
                BookEntity = new Book()
                {
                    Name = e.Book.Name,
                    BookImgUrl = e.Book.BookImgUrl
                };
                context.Books.Add(BookEntity);
                context.SaveChanges();
            }


            // Create the Event Entity
            string dtObjFormat = "dd MMM yyyy HH:mm";
            DateTime dt;
            var EventEntity = new Event()
            {
                Author = AuthorEntity,
                Book = BookEntity,
                Info = e.Info,
                Start = DateTime.TryParseExact(e.Date + " " + e.Time, dtObjFormat, CultureInfo.InvariantCulture, DateTimeStyles.None, out dt) ? dt : new DateTime(),
                Location = LocationEntity
            };
            context.Events.Add(EventEntity);
            context.SaveChanges();
        }
        catch
        {
            Console.WriteLine("Something went wrong!");
        }
    }
    Console.WriteLine("Looped through all Events");
}

上面的代码尝试创建实体并将它们保存到数据库中。并且当需要时,重新使用保存的实体。

例如,在我的 XML 文件中,一个作者出现了两次,但我不想为该作者创建两条记录,因为我已经在前一个循环中为同一作者创建了一条记录。尽管在我看来我有代码可以解决这个问题(见上文),但由于某种原因,它仍然会创建多个作者记录。书籍也有同样的问题。

getAuthorByName(String authorName)方法具有以下代码:

/// <summary>
/// A method to get an Author Entity by name. If no Author exists, then
/// NULL is returned. If two authors exist with the exact same name,
/// then the first encountered is returned.
/// </summary>
/// <param name="authorName">The name of the Author.</param>
/// <returns>The Author Entity</returns>
public Author getAuthorByName(String authorName)
{
    using (var context = new BSContext())
    {
        return context.Authors.FirstOrDefault(x => x.Name == authorName);
    }
}

另外两种方法getBookByName(String bookName)getLocationByNameAddressAndPostCode(String lName, String lAddress, String lPostCode)上面的方法都有类似的逻辑。

问题:停止数据库中实体 Book 和 Author 的记录重复。

4

1 回答 1

1

您应该在这里注意的是,您使用了 2 个活动的 BSContext 对象。实体跟踪分别与这些上下文中的每一个一起发生。Aka Author 将居住在一个中,而不是两者中,除非您在两者中查询它。

完成 getAuthorByName 方法后,作者实体将与任何实体上下文分离。您需要做的是将此实体重新附加到外部上下文(也就是最上面的代码示例中的那个)。如果你不这样做,就像上面的代码一样,BSContext 不知道它是一个现有的实体,并认为它是一个新的实体。导致新的作者被插入到数据库中。

或者你可以尝试这样做。

/// <summary>
/// A method to get an Author Entity by name. If no Author exists, then
/// NULL is returned. If two authors exist with the exact same name,
/// then the first encountered is returned.
/// </summary>
/// <param name="authorName">The name of the Author.</param>
/// <returns>The Author Entity</returns>
public Author getAuthorByName(BSContext context, String authorName)
{
        return context.Authors.FirstOrDefault(x => x.Name == authorName);
}

然后像这样调用解析器

var AuthorEntity = parser.getAuthorByName(context, e.Author);
于 2013-04-15T20:27:37.970 回答