后台:我正在解析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重复记录。
答案 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);