无法让我的实体尊重域的参照完整性

时间:2013-04-15 19:58:57

标签: entity-framework ef-code-first entity-framework-4.1 referential-integrity

后台:我正在解析XML文件(图书签名事件信息),然后尝试通过Entity Framework Code First(借助Entity Framework Power)基于Parsed数据创建数据库记录工具Beta 3)。

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

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 and Author重复记录。

1 个答案:

答案 0 :(得分:1)

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

完成getAuthorByName方法后,Author实体将与任何实体上下文分离。您需要做的是将此实体重新附加到外部上下文(也就是最顶层代码示例中的实体)。如果不这样做,就像在上面的代码中一样,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);