序列包含多个元素c#Entity Seed

时间:2017-05-30 08:52:43

标签: c# entity-framework csv

尝试从CSV实体中播种国家/地区,但在运行Update-Database时遇到此错误。如果我删除表并运行Update-Database,则错误不会显示,但如果我再次运行Update-Database。

CSV文件

Name,
China,
India,
United States,
Indonesia,
Brazil,
Pakistan,
United Kingdom,
Bangladesh,
Russia,
Japan,
Mexico,
Philippines,
Vietnam,
Ethiopia,
Egypt,
Germany,
Iran,
Turkey,
Democratic Republic of the Congo,
Thailand,
France,
Italy,
Burma,
South Africa,
South Korea,
Colombia,
Spain,
Ukraine,

我的国家模式

namespace Domain
{
    public class Country : BaseModel
    {
        public string Name { get; set; }
    }
}



using System.ComponentModel.DataAnnotations;

namespace Domain
{
    public class BaseModel
    {
        [Key]
        public int Id { get; set; }
    }
}

种子

var assembly = Assembly.GetExecutingAssembly();

const string country = "Service.Migrations.Seed.countries.csv";
            using (var stream = assembly.GetManifestResourceStream(country))
            {
                using (var reader = new StreamReader(stream, Encoding.UTF8))
                {
                    var csvReader = new CsvReader(reader);
                    csvReader.Configuration.Delimiter = ",";
                    csvReader.Configuration.WillThrowOnMissingField = false;
                    var countries = csvReader.GetRecords<Country>().ToArray();
                }
            }

错误

No pending explicit migrations.
Running Seed method.
System.InvalidOperationException: Sequence contains more than one element
   at System.Linq.Enumerable.SingleOrDefault[TSource](IEnumerable`1 source)
   at System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.<GetElementFunction>b__2[TResult](IEnumerable`1 sequence)
   at System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.ExecuteSingle[TResult](IEnumerable`1 query, Expression queryRoot)
   at System.Data.Entity.Core.Objects.ELinq.ObjectQueryProvider.System.Linq.IQueryProvider.Execute[TResult](Expression expression)
   at System.Data.Entity.Internal.Linq.DbQueryProvider.Execute[TResult](Expression expression)
   at System.Linq.Queryable.SingleOrDefault[TSource](IQueryable`1 source, Expression`1 predicate)
   at System.Data.Entity.Migrations.DbSetMigrationsExtensions.AddOrUpdate[TEntity](DbSet`1 set, IEnumerable`1 identifyingProperties, InternalSet`1 internalSet, TEntity[] entities)
   at System.Data.Entity.Migrations.DbSetMigrationsExtensions.AddOrUpdate[TEntity](IDbSet`1 set, Expression`1 identifierExpression, TEntity[] entities)
   at Service.Migrations.Configuration.Seed(HotelContext context) in C:\Hotel+\Service\Migrations\Configuration.cs:line 55
   at System.Data.Entity.Migrations.DbMigrationsConfiguration`1.OnSeed(DbContext context)
   at System.Data.Entity.Migrations.DbMigrator.SeedDatabase()
   at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.SeedDatabase()
   at System.Data.Entity.Migrations.DbMigrator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
   at System.Data.Entity.Migrations.Infrastructure.MigratorLoggingDecorator.Upgrade(IEnumerable`1 pendingMigrations, String targetMigrationId, String lastMigrationId)
   at System.Data.Entity.Migrations.DbMigrator.UpdateInternal(String targetMigration)
   at System.Data.Entity.Migrations.DbMigrator.<>c__DisplayClassc.<Update>b__b()
   at System.Data.Entity.Migrations.DbMigrator.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)
   at System.Data.Entity.Migrations.Infrastructure.MigratorBase.EnsureDatabaseExists(Action mustSucceedToKeepDatabase)
   at System.Data.Entity.Migrations.DbMigrator.Update(String targetMigration)
   at System.Data.Entity.Migrations.Infrastructure.MigratorBase.Update(String targetMigration)
   at System.Data.Entity.Migrations.Design.ToolingFacade.UpdateRunner.Run()
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.AppDomain.DoCallBack(CrossAppDomainDelegate callBackDelegate)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Run(BaseRunner runner)
   at System.Data.Entity.Migrations.Design.ToolingFacade.Update(String targetMigration, Boolean force)
   at System.Data.Entity.Migrations.UpdateDatabaseCommand.<>c__DisplayClass2.<.ctor>b__0()
   at System.Data.Entity.Migrations.MigrationsDomainCommand.Execute(Action command)
Sequence contains more than one element

2 个答案:

答案 0 :(得分:2)

您的ID是自动递增的,因此如果您不检查数据库中是否已存在当前的国家/地区名称,则EF会创建一个带有新ID的新条目...

您有两种解决方案可以避免这种情况:

解决方案1:

在数据库中的国家/地区内循环,并检查名称是否已存在。如果是这种情况不再添加它。

解决方案2:

国家/地区名称设置为唯一,如下所示:

namespace Domain
{
    public class Country : BaseModel
    {
        [Index(IsUnique = true)]
        public string Name { get; set; }
    }
}

当您尝试添加已在数据库中退出的名称时,这将引发异常。您可以使用 try-catch 管理错误,并记录例外情况。

答案 1 :(得分:1)

这就是我解决问题的方法。

var assembly = Assembly.GetExecutingAssembly();
const string country = "Service.Migrations.Seed.countries.csv";
            using (var stream = assembly.GetManifestResourceStream(country))
            {
                using (var reader = new StreamReader(stream, Encoding.UTF8))
                {
                    var csvReader = new CsvReader(reader);
                    csvReader.Configuration.Delimiter = ",";
                    csvReader.Configuration.WillThrowOnMissingField = false;
                    var countries = csvReader.GetRecords<Country>().ToArray();
                    foreach (var c in countries)
                    {
                        var check = context.Countries.FirstOrDefault(p => p.Name == c.Name);
                        if (check == null)
                        {
                            context.Countries.Add(c);
                            context.SaveChanges();
                        }
                    }
                }
            }