2016-03-14 3 views
1

Я новичок в инфраструктуре Entity. У меня есть приложение, которое считывает данные из xml и сохраняет их в базе данных.Слияние данных в db-таблице с новыми данными

Чтение и вставка данных - это ежедневная работа.

В Entity Framework, как я могу объединить новые данные, если есть новые данные в xml со старыми данными в одной таблице?

Этот код вставляет новые данные при его вызове, который выделяет дубликаты объектов. И я не хочу, чтобы данные, хранящиеся в db, были изменены.

public void MyCustomTypes(string Xml) 
{ 
    XDocument xDoc = XDocument.Parse(Xml); 
    List<Category> allCateogries = new List<Category>(); 

    var db = new MyContext(); 

    var caq1 = xDoc.Descendants().Where(e => e.Name.LocalName.Contains("FaceAdd")).Elements().Where(n => n.Name.LocalName.Contains("Buildingtype")).Select(v=>v.Value).Distinct().ToList(); 

    foreach (var x in caq1) 
    { 
     Category category = new Category 
       { 
        Name = x.ToString(), 
        NrOfFaceAdds= getNr(x.ToString(), xDoc) 
       }; 
     allCateogries.Add(category);     
    } 

    db.Categories.AddRange(allCateogries); 
    db.SaveChanges(); 
} 
+0

Принеси старые данные из БД и использовать союз, чтобы объединить списки вместе: http://msdn.microsoft.com/en-us/library/ bb341731.aspx Затем вставьте значения. –

+0

Проверить обновление для моего ответа – Fabjan

ответ

1

Сначала получите все записи из БД, а затем с помощью этого удалить дубликаты в новом списке, проверяя, если Name и NrOfFaceAdds уже не в БД.

var oldCategories = db.Categories.ToList(); 
var filteredCategories = allCateogries.Where(i => !oldCategories.Any(c => c.Name == i.Name) && !oldCategories.Any(c=> c.NrOfFaceAdds == i.NrOfFaceAdds));  

db.Categories.AddRange(filteredCategories); 
db.SaveChanges(); 
+1

К сожалению, кроме того, это путь. Я что-то смутил. Спасибо :) –

+0

Нет, он по-прежнему сохраняет дублированные объекты. –

+0

'.Except()' будет проверять объекты по своим хэш-кодам и не будет удалять дубликаты, потому что их коды имеют разные – Fabjan

0

Давайте реорганизовать ваш код немного с LINQ первый:

public void MyCustomTypes(string Xml) 
{ 
    XDocument xDoc = XDocument.Parse(Xml); 
    var db = new MyContext(); 

    var caq1 = xDoc.Descendants().Where(e => e.Name.LocalName.Contains("FaceAdd")).Elements().Where(n => n.Name.LocalName.Contains("Buildingtype")).Select(v=>v.Value).Distinct().ToList(); 

    List<Category> allCateogries = caq1.Select(x => 
     new Category 
     { 
      Name = x.ToString(), 
      NrOfFaceAdds= getNr(x.ToString(), xDoc) 
     }).ToList(); 

    // now we need to add only unique items from this list to database 
    // one way to solve this problem is to create custom hashset and check if object's Name is there 
    // this is also very fast as HashSet<T> lookup is almost O(1) 

    HashSet<string> catNames = new HashSet<string>(db.Categories.Select(c => c.Name)); 

    db.Categories.AddRange(allCateogries.Where(c => !catNames.Contains(c.Name))); 
} 

Другим способом заключается в использовании .Except() метода с пользовательским IEqualityComparer. Нам нужно это сделать, потому что по умолчанию для сравнения будет проверяться хэш-код объекта, а не свойства.

public class MyEqualityComparer : IEqualityComparer<Category> 
{ 
    public bool Equals(Category x, Category y) 
    { 
     return x.Name == y.Name; 
    } 

    public int GetHashCode(Category obj) 
    { 
     return obj.Name; 
    } 
} 

Тогда мы можем сделать:

db.Categories.AddRange(allCateogries.Except(db.Categories, new MyEqualityComparer())); 
+0

Спасибо, Это решило мою проблему –

Смежные вопросы