我需要订购DbSet<>的创建在DbContext中。因为:
顺便说一下,DbSets已经在DbContext中订购,但在创建迁移时似乎没有效果。
在我的DbContext中:
public class CmsDbContext : DbContext
{
// Basic
public DbSet<Country> Countries { get; set; }
public DbSet<District> Districts { get; set; }
public DbSet<Province> Provinces { get; set; }
public DbSet<City> Cities { get; set; }
public DbSet<Area> Areas { get; set; }
public DbSet<CustomerType> CustomerTypes { get; set; }
public DbSet<IdType> IdTypes { get; set; }
public DbSet<IncomeType> IncomeTypes { get; set; }
public DbSet<OutcomeType> OutcomeTypes { get; set; }
public DbSet<PaymentType> PaymentTypes { get; set; }
}
如你所见,国家是第一个。 发出后
add-migration initial
DbSets的顺序不是我想要的:
public partial class initial : DbMigration
{
public override void Up()
{
CreateTable(
"dbo.Area",
c => new
{
AreaId = c.Int(nullable: false, identity: true),
CityId = c.Int(nullable: false),
AreaArabicName = c.String(nullable: false, maxLength: 35, unicode: false),
AreaEnglishName = c.String(nullable: false, maxLength: 35, unicode: false),
AddedDate = c.DateTime(),
ModifiedDate = c.DateTime(),
})
.PrimaryKey(t => t.AreaId)
.ForeignKey("dbo.City", t => t.CityId)
.Index(t => t.CityId);
CreateTable(
"dbo.City",
c => new
{
CityId = c.Int(nullable: false, identity: true),
ProvinceId = c.Int(nullable: false),
CityArabicName = c.String(nullable: false, maxLength: 35, unicode: false),
CityEnglishName = c.String(nullable: false, maxLength: 35, unicode: false),
AddedDate = c.DateTime(),
ModifiedDate = c.DateTime(),
})
.PrimaryKey(t => t.CityId)
.ForeignKey("dbo.Province", t => t.ProvinceId)
.Index(t => t.ProvinceId);
依旧......
请注意,国家/地区不是第一个要创建的表。
当我发出:
update-database
创建数据库,表也创建了,但种子方法没有。我有例外:
The INSERT statement conflicted with the FOREIGN KEY constraint "FK_dbo.Area_dbo.City_CityId".
如果我停止播种城市,就不会发生这种情况。
我希望现在问题很清楚。
这是城市
的种子class CityDefaultData
{
private readonly string[,] _cities = new string[,]
{
{"1", "الرياض", "Riyadh"},
{"2", "جدة", "Jeddah"},
{"3", "الدمام", "Dammam"},
{"4", "بريدة", "Buraidah"}
};
private readonly List<City> _newCitiess = new List<City>();
public List<City> GetDefaultCity()
{
for (var i = 0; i <= _cities.GetUpperBound(0); i++)
{
_newCitiess.Add(new City()
{
ProvinceId = Convert.ToInt32(_cities[i, 0]),
CityArabicName = _cities[i, 1],
CityEnglishName = _cities[i, 2]
});
}
return _newCitiess;
}
}
区域的种子:
class AreaDefaultData
{
private readonly string[,] _areas = new string[,]
{
{"1", "السلام", "Salam"},
{"1", "العليا", "Olayya"},
{"1", "الروابي", "Rawabi"},
{"1", "القدس", "Quds"},
{"1", "المنار", "Manar"},
{"2", "السلام", "Salam"},
{"2", "العليا", "Olayya"},
{"2", "الروابي", "Rawabi"},
{"2", "القدس", "Quds"},
{"2", "المنار", "Manar"}
};
private readonly List<Area> _newAreas = new List<Area>();
public List<Area> GetDefaultArea()
{
for (var i = 0; i <= _areas.GetUpperBound(0); i++)
{
_newAreas.Add(new Area()
{
CityId = Convert.ToInt32(_areas[i, 0]),
AreaArabicName = _areas[i, 1],
AreaEnglishName = _areas[i, 2]
});
}
return _newAreas;
}
}
这是我的DbInitialize
class DbInitializer
{
public void DataSeed(CmsDbContext context)
{
// Country
List<Country> coutry =
new CountryDefaultData().GetDefaultCountry();
coutry.ForEach(e => context.Countries.Add(e));
context.Countries.AddOrUpdate();
// District
List<District> district =
new DistrictDefaultData().GetDefaultDistrict();
district.ForEach(e => context.Districts.Add(e));
context.Districts.AddOrUpdate();
// Province
List<Province> province =
new ProvinceDefaultData().GetDefaultProvince();
province.ForEach(e => context.Provinces.Add(e));
context.Provinces.AddOrUpdate();
// City
List<City> city =
new CityDefaultData().GetDefaultCity();
city.ForEach(e => context.Cities.Add(e));
context.Cities.AddOrUpdate();
// Area
List<Area> area =
new AreaDefaultData().GetDefaultArea();
area.ForEach(e => context.Areas.Add(e));
context.Areas.AddOrUpdate();
// Id Type
List<IdType> idType =
new IdTypeDefultData().GetDefaultIdTypes();
idType.ForEach(e => context.IdTypes.Add(e));
context.IdTypes.AddOrUpdate();
// Customer Type
List<CustomerType> customerType =
new CustomerTypeDefaultData().GetDefaultCustomerType();
customerType.ForEach(e => context.CustomerTypes.Add(e));
context.CustomerTypes.AddOrUpdate();
// Income Type
List<IncomeType> incomeType =
new IncomeTypeDefaultData().GetDefaultIncomeType();
incomeType.ForEach(e => context.IncomeTypes.Add(e));
context.IncomeTypes.AddOrUpdate();
// Outcome Type
List<OutcomeType> outcomeType =
new OutcomeTypeDefaultData().GetDefaultOutcomeType();
outcomeType.ForEach(e => context.OutcomeTypes.Add(e));
context.OutcomeTypes.AddOrUpdate();
// Payment Type
List<PaymentType> paymentType =
new PaymentTypeDefaultData().GetDefaultPaymentType();
paymentType.ForEach(e => context.PaymentTypes.Add(e));
context.PaymentTypes.AddOrUpdate();
}
}
最后:
internal sealed class Configuration : DbMigrationsConfiguration<CMS.Model.Domain.CmsDbContext>
{
public Configuration()
{
AutomaticMigrationsEnabled = true;
}
protected override void Seed(CMS.Model.Domain.CmsDbContext context)
{
DbInitializer all = new DbInitializer();
all.DataSeed(context);
}
}
答案 0 :(得分:1)
好吧,最后在清除了关于创建表格,播种数据和添加数据的顺序的一些误解后,我们已经达到了一些可以给出一些有希望的有用见解的观点。
此方法专门用于播种数据,因此您处于正确的轨道上。但是你并没有有效地使用它,因为你没有输入任何实体。以下是您如何使用它的示例:
var cities = new City[]
{
new City { ProvinceId = 1, CityArabicName = "الرياض", CityEnglishName = "Riyadh"},
new City { ProvinceId = 2, CityArabicName = "جدة", CityEnglishName = "Jeddah"},
new City { ProvinceId = 3, CityArabicName = "الدمام", CityEnglishName = "Dammam"},
new City { ProvinceId = 4, CityArabicName = "بريدة", CityEnglishName = "Buraidah"}
};
context.Cities.AddOrUpdate(c => c.CityArabicName, cities);
lambda表达式c => c.CityArabicName
告诉EF按CityArabicName
查找城市。如果已存在具有该名称的城市,则该城市将标记为已修改,否则将标记为新城市。请注意,AddOrUpdate
不会保存任何数据,最后由SaveChanges
个CityId
电话完成。
如果您不提供此lambda表达式,则EF会假定主键0
是查找现有城市的关键。好吧,它们未在cities
中指定(即Seed
)。因此,找不到现有城市,Area
方法将始终复制您的城市。因此,当自动生成主键时,您总是需要一些自然键,以便EF识别现有实体。
但即使您在种子数据中输入主键值,EF也会忽略它们。 使用自动生成的主键,您无法为主键值设定种子。
好吧,如果主键值不可预测,也不能为硬编码的外键值设置种子。这正是您对CityId
所做的。现在,不可否认,当城市 播种时,你得到FK违规是很奇怪的,而不是当它们没有播种时。毕竟,生成TransactionScope
s 1和2的可能性很大(尽管Sql Server可以决定以更高的值开始生成)。所以我无法解释你的发现,但我做知道你必须修复你的播种代码。
有两种方法可以在播种脚本中将对象绑定在一起:
将整个脚本包裹在SaveChanges
中,多次调用SaveChanges
,并捕获生成的主键值,以便在后续步骤中将它们分配给实体属性。我不是很喜欢这个选项,但有时你必须使用它。更好的选择是 -
创建对象图。也就是说,创建具有嵌套实体的实体并通过一次City
调用保存它们。在您的情况下,这意味着public virtual ICollection<Area> Areas { get; set; }
应该具有导航属性...
var cities = new City[]
{
new City { ProvinceId = 1, CityArabicName = "الرياض", CityEnglishName = "Riyadh",
Areas = areas1 },
new City { ProvinceId = 2, CityArabicName = "جدة", CityEnglishName = "Jeddah",
Areas = areas2 },
new City { ProvinceId = 3, CityArabicName = "الدمام", CityEnglishName = "Dammam"},
new City { ProvinceId = 4, CityArabicName = "بريدة", CityEnglishName = "Buraidah"}
};
...并且您应该填充种子实体中的区域:
areas1
...其中areas2
和AddOrUpdate
显然属于前两个城市的两个区域集合。现在,您只前往Area
城市,因为如果必须添加城市,则必须添加其中的区域。
这并不能说明整个故事。播种相关数据可能很难。如果您必须在应用程序的更高版本中向City
添加Area
,该怎么办?如果您要更新AddOrUpdate
或删除一个,该怎么办?这通常需要更多冗长的步骤,不再使用Option Explicit
Dim sheetCount As Integer
Dim datatoFind
Sub Button1_Click()
Find_File
End Sub
Private Sub Find_File()
Dim c As Range
Dim counter As Integer
Dim currentSheet As Integer
Dim notFound As Boolean
notFound = True
For Each c In Selection.Cells
On Error Resume Next
currentSheet = ActiveSheet.Index
datatoFind = StrConv(c.Value, vbLowerCase)
If datatoFind = "" Then Exit Sub
sheetCount = ActiveWorkbook.Sheets.Count
If IsError(CDbl(datatoFind)) = False Then datatoFind = CDbl(datatoFind)
For counter = 1 To sheetCount
Sheets(counter).Activate
Cells.Find(What:=datatoFind, After:=ActiveCell, LookIn:=xlValues, LookAt _
:=xlPart, SearchOrder:=xlByRows, SearchDirection:=xlNext, MatchCase:= _
False, SearchFormat:=False).Activate
If InStr(1, StrConv(ActiveCell.Value, vbLowerCase), datatoFind) Then
notFound = False
Sheets(counter).Activate
Range("datatoFind").Select
Exit For
End If
Next counter
If notFound = True Then
MsgBox ("Value not found")
Sheets(counter).Activate
Else
Exit Sub
End If
Next c
End Sub
。
答案 1 :(得分:0)
播种
创建Country
的对象,在District
添加District
中添加Province
,Province
添加City
&gt; Area
&gt; TypeID
中的TypeID
添加该层次结构的客户数据。
现在分别向Area
或TypeID
添加另一个City
或Area
。
因此Country
的对象有多个区域,每个区域有多个省,每个省都有多个城市......同样明智。
现在将此对象Country
添加到函数:
context.Countries.Add(
并在此添加多个国家/地区。