diff --git a/package/EntityFramework.Seeder.EF6.0.3.0.nupkg b/package/EntityFramework.Seeder.EF6.0.3.0.nupkg new file mode 100644 index 0000000..c268c4d Binary files /dev/null and b/package/EntityFramework.Seeder.EF6.0.3.0.nupkg differ diff --git a/package/EntityFramework.Seeder.EF6.0.3.1.nupkg b/package/EntityFramework.Seeder.EF6.0.3.1.nupkg new file mode 100644 index 0000000..25ae13a Binary files /dev/null and b/package/EntityFramework.Seeder.EF6.0.3.1.nupkg differ diff --git a/package/EntityFramework.Seeder.EF6.0.3.2.nupkg b/package/EntityFramework.Seeder.EF6.0.3.2.nupkg new file mode 100644 index 0000000..f3a71a2 Binary files /dev/null and b/package/EntityFramework.Seeder.EF6.0.3.2.nupkg differ diff --git a/src/EntityFramework.Seeder.EF6.Tests/CountriesFileWithErrors.csv b/src/EntityFramework.Seeder.EF6.Tests/CountriesFileWithErrors.csv new file mode 100644 index 0000000..fa26ed0 --- /dev/null +++ b/src/EntityFramework.Seeder.EF6.Tests/CountriesFileWithErrors.csv @@ -0,0 +1,5 @@ +CodeNotRight,NameAlsoNotRight +AT,Austria +AU,Australia +CA,Canada +US,United States \ No newline at end of file diff --git a/src/EntityFramework.Seeder.EF6.Tests/EntityFramework.Seeder.EF6.Tests.csproj b/src/EntityFramework.Seeder.EF6.Tests/EntityFramework.Seeder.EF6.Tests.csproj index 29fe5db..55f93fb 100644 --- a/src/EntityFramework.Seeder.EF6.Tests/EntityFramework.Seeder.EF6.Tests.csproj +++ b/src/EntityFramework.Seeder.EF6.Tests/EntityFramework.Seeder.EF6.Tests.csproj @@ -79,6 +79,7 @@ + @@ -98,6 +99,9 @@ Always + + Always + diff --git a/src/EntityFramework.Seeder.EF6.Tests/when_an_error_occurs_while_seeding_a_dbset.cs b/src/EntityFramework.Seeder.EF6.Tests/when_an_error_occurs_while_seeding_a_dbset.cs new file mode 100644 index 0000000..6187cf4 --- /dev/null +++ b/src/EntityFramework.Seeder.EF6.Tests/when_an_error_occurs_while_seeding_a_dbset.cs @@ -0,0 +1,74 @@ +using System; +using System.IO; +using System.Linq; +using System.Runtime.Serialization.Formatters.Binary; +using EntityFramework.Seeder.EF6.Tests.Domain; +using Given.Common; +using Given.NUnit; +using NUnit.Framework; + +namespace EntityFramework.Seeder.EF6.Tests +{ + [Story(AsA = "developer", + IWant = "see exception details", + SoThat = "I can diagnose errors that might happen while seeding a dbset")] + public class while_an_error_occurs_while_seeding_a_dbset : Scenario + { + public static CountryContext _context; + + given an_empty_context = () => + { + _context = new CountryContext(); + _context.DeleteAll(); + }; + + + [then] + [ExpectedException(typeof(Exception))] + public void when_seeding_from_a_file_with_unmapped_columns() + { + _context.Countries.SeedFromFile("CountriesFileWithErrors.csv", c => c.Code); + } + + [then] + public void the_exception_should_be_serializable() + { + Exception exception = null; + try + { + _context.Countries.SeedFromFile("CountriesFileWithErrors.csv", c => c.Code); + } + catch (Exception ex) + { + exception = ex; + } + + Assert.IsNotNull(exception); + + string exceptionToString = exception.ToString(); + + // Round-trip the exception: Serialize and de-serialize with a BinaryFormatter + BinaryFormatter bf = new BinaryFormatter(); + using (MemoryStream ms = new MemoryStream()) + { + // "Save" object state + bf.Serialize(ms, exception); + + // Re-use the same stream for de-serialization + ms.Seek(0, 0); + + // Replace the original exception with de-serialized one + exception = (Exception)bf.Deserialize(ms); + } + + // Double-check that the exception message and stack trace (owned by the base Exception) are preserved + Assert.AreEqual(exceptionToString, exception.ToString(), "ex.ToString()"); + } + + [TestFixtureTearDown] + public void TearDown() + { + _context.Dispose(); + } + } +} \ No newline at end of file diff --git a/src/EntityFramework.Seeder.EF6/EFSeederException.cs b/src/EntityFramework.Seeder.EF6/EFSeederException.cs new file mode 100644 index 0000000..961f63a --- /dev/null +++ b/src/EntityFramework.Seeder.EF6/EFSeederException.cs @@ -0,0 +1,34 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Runtime.Serialization; +using System.Text; +using System.Threading.Tasks; + +namespace EntityFramework.Seeder +{ + /// + /// Represents an exception that has occurred while seeding a dbset. + /// Wraps the underlying exception and is serializable so that the exception message can be + /// properly displayed in the package manager console in Visual Studio + /// + [Serializable] + public class EfSeederException : Exception, ISerializable + { + public EfSeederException() + { + } + + public EfSeederException(string message) : base(message) + { + } + + public EfSeederException(string message, Exception innerException) : base(message, innerException) + { + } + + protected EfSeederException(SerializationInfo info, StreamingContext context) : base(info, context) + { + } + } +} diff --git a/src/EntityFramework.Seeder.EF6/EntityFramework.Seeder.EF6.csproj b/src/EntityFramework.Seeder.EF6/EntityFramework.Seeder.EF6.csproj index c04b7bb..a63ec74 100644 --- a/src/EntityFramework.Seeder.EF6/EntityFramework.Seeder.EF6.csproj +++ b/src/EntityFramework.Seeder.EF6/EntityFramework.Seeder.EF6.csproj @@ -52,6 +52,7 @@ + diff --git a/src/EntityFramework.Seeder.EF6/Properties/AssemblyInfo.cs b/src/EntityFramework.Seeder.EF6/Properties/AssemblyInfo.cs index 1daca51..e29ad50 100644 --- a/src/EntityFramework.Seeder.EF6/Properties/AssemblyInfo.cs +++ b/src/EntityFramework.Seeder.EF6/Properties/AssemblyInfo.cs @@ -10,7 +10,7 @@ [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] [assembly: AssemblyProduct("EntityFramework.Seeder")] -[assembly: AssemblyCopyright("Copyright © 2014")] +[assembly: AssemblyCopyright("Copyright © 2015")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("0.2.1.0")] -[assembly: AssemblyFileVersion("0.2.1.0")] +[assembly: AssemblyVersion("0.3.2.0")] +[assembly: AssemblyFileVersion("0.3.2.0")] diff --git a/src/EntityFramework.Seeder.EF6/Seeder.cs b/src/EntityFramework.Seeder.EF6/Seeder.cs index a9ceadf..60d3a09 100644 --- a/src/EntityFramework.Seeder.EF6/Seeder.cs +++ b/src/EntityFramework.Seeder.EF6/Seeder.cs @@ -13,6 +13,22 @@ namespace EntityFramework.Seeder /// public static class Seeder { + static Seeder() + { + AppDomain.CurrentDomain.AssemblyResolve += ResolveAssembly; + } + + private static Assembly ResolveAssembly(object sender, ResolveEventArgs args) + { + if (new AssemblyName(args.Name).Name == "EntityFramework.Seeder.EF6") + { + return typeof (Seeder).Assembly; + } + + return null; + + } + /// /// Seeds a DBSet from a CSV file that will be read from the specified stream /// @@ -23,23 +39,33 @@ public static class Seeder /// Any additonal complex mappings required public static void SeedFromStream(this IDbSet dbSet, Stream stream, Expression> identifierExpression, params CsvColumnMapping[] additionalMapping) where T : class { - using (StreamReader reader = new StreamReader(stream)) + try { - CsvReader csvReader = new CsvReader(reader); - var map = csvReader.Configuration.AutoMap(); - map.ReferenceMaps.Clear(); - csvReader.Configuration.RegisterClassMap(map); - csvReader.Configuration.WillThrowOnMissingField = false; - while (csvReader.Read()) + using (StreamReader reader = new StreamReader(stream)) { - var entity= csvReader.GetRecord(); - foreach (CsvColumnMapping csvColumnMapping in additionalMapping) + CsvReader csvReader = new CsvReader(reader); + var map = csvReader.Configuration.AutoMap(); + map.ReferenceMaps.Clear(); + csvReader.Configuration.RegisterClassMap(map); + csvReader.Configuration.WillThrowOnMissingField = false; + while (csvReader.Read()) { - csvColumnMapping.Execute(entity, csvReader.GetField(csvColumnMapping.CsvColumnName)); + var entity = csvReader.GetRecord(); + foreach (CsvColumnMapping csvColumnMapping in additionalMapping) + { + csvColumnMapping.Execute(entity, csvReader.GetField(csvColumnMapping.CsvColumnName)); + } + dbSet.AddOrUpdate(identifierExpression, entity); } - dbSet.AddOrUpdate(identifierExpression, entity); } } + catch (Exception ex) + { + string message = string.Format("Error Seeding DbSet<{0}>: {1}", dbSet.GetType().GenericTypeArguments[0].FullName, ex.ToString()); + Exception innerException = ex.GetType().IsSerializable ? ex : null; + //Unfortunately I need to use a root exception here as this is the only way for the Update-Database powershell script to properly report the error + throw new Exception(message, innerException); + } } ///