0

I have an Employee class like below

 public class Employee
    {
        public int EmployeeID { get; set; }
        public string Name { get; set; }
        public int Age { get; set; }
        public DateTime DOB { get; set; }
    }

I am using Entity Framework to retrieve the Employee data from the database like below

using (var dbContext = new EmployeeEntities())
{
    List<Employee> employeeList = new List<Employee>();
    employeeList = dbContext.employee.Select(x => new Employee
                                        {
                                            EmployeeID = x.EmployeeID,
                                            Name = x.Name,
                                            Age = x.Age,
                                            DOB = x.DOB
                                        }).ToList();
}

And then i serialize the list and save it as an XML file.

if (employeeList.Count > 0)
{
     XmlSerializer mySerializer = new XmlSerializer(typeof(List<Employee>));
     TextWriter myWriter = new StreamWriter("D:\\Employee.xml", true);
     mySerializer.Serialize(myWriter, employeeList);
     myWriter.Close();
}

My requirement here is to save the result set to Multiple XML files based on the page size that i specify. E.g if the Employee table contains 536 rows and my page size is 100, then i should save it in 6 XML files containing 100,100,100,100,100 and 36 rows respectively. How do i achieve this using entity framework??

raja_89
  • 3
  • 5

2 Answers2

0

You can use .Skip() and .Take() to do the trick.

.Take() will take the defined amount of items from the list, if there are less, it will take all. .Skip() will skip the amount defined.

By having the tmp variable, you can work the employeeList off and save each file.

  if (employeeList.Count > 0)
        {
            int take = 100;
            int i = 0;
            while (employeeList.Any())
            {
                i++;
                var tmp = employeeList.Take(take)ToList();
                employeeList = employeeList.Skip(take).ToList();
                XmlSerializer mySerializer = new XmlSerializer(typeof(List<Employee>));
                TextWriter myWriter = new StreamWriter("D:\\Employee"+i+".xml", true);
                mySerializer.Serialize(myWriter, tmp);
                myWriter.Close();
            }
        }
Vulpex
  • 1,041
  • 8
  • 19
  • But note that performance may suffer if you have lots of records... https://www.make-awesome.com/2010/08/batch-or-partition-a-collection-with-linq/ – Sebastian Hofmann Mar 16 '18 at 12:55
  • I am getting the following exception if i follow this approach. Unable to cast object of type 'd__31`1[Employee]' to type 'System.Collections.Generic.List`1[Employee]'. – raja_89 Mar 16 '18 at 13:14
  • @raja_89 strange, it complied just fine for me. I've added .ToList(), that should fix the type mismatch. – Vulpex Mar 16 '18 at 13:45
0

In the past I've done this with this Batch extension method:

public static class EnumerableExtensions
{
    /// <summary> 
    /// Splits the values in an enumerable by position into batches of the specified size 
    /// </summary> 
    public static IEnumerable<IEnumerable<T>> Batch<T>(this IEnumerable<T> items, int batchSize)
    {
        using (var e = items.GetEnumerator())
        {
            while (e.MoveNext()) // check before entering the loop 
            {
                yield return BatchOf(e, batchSize);
            }
        }
    }

    private static IEnumerable<T> BatchOf<T>(IEnumerator<T> e, int batchSize)
    {
        for (var i = 0; i < batchSize; i++)
        {
            if (i > 0 && !e.MoveNext()) // already checked once before entering the loop / so only check on subsequent iterations 
            {
                yield break;
            }
            yield return e.Current;
        }
    }
}

Then it's simple enough to use:

int i = 0;
foreach (var batch in employeeList.Batch(100))
{
    XmlSerializer mySerializer = new XmlSerializer(typeof(List<Employee>));
    TextWriter myWriter = new StreamWriter($"D:\\Employee{i++}.xml", true);
    mySerializer.Serialize(myWriter, batch.ToList());
    myWriter.Close();
}
Jono
  • 1,964
  • 4
  • 18
  • 35