我有一个名为Employee的POCO实体。 然后我有第二个名为Case的POCO实体。
我想要一个看起来像这样的导航属性:
public View getView(int position, View view, ViewGroup parent) {
if (view == null) {
holder = new Holder();
if (position == 3) {
view = View.inflate(getContext(), R.layout.list_item_with_expandable_new, null);
} else {
view = View.inflate(getContext(), R.layout.list_item_text, null);
}
view.setTag(holder);
} else {
holder = (Holder) view.getTag();
}
if (position != 3) {
holder.textView = (TextView) view.findViewById(R.id.text);
holder.textView.setText(mHelpLabels.get(position));
Drawable[] iconLeft = {Util.getCustomDrawableColor(getActivity(),R.drawable.ic_favorite_18dp,R.color.beco_logout_red, PorterDuff.Mode.SRC_ATOP),
Util.getCustomDrawableColor(getActivity(), R.drawable.ic_checkin_18dp, R.color.beco_logout_red, PorterDuff.Mode.DST_IN),
Util.getCustomDrawableColor(getActivity(), R.drawable.ic_faq, R.color.beco_white, PorterDuff.Mode.DST_IN),
Util.getCustomDrawableColor(getActivity(), R.drawable.ic_feedback, R.color.beco_white, PorterDuff.Mode.DST_IN),
Util.getCustomDrawableColor(getActivity(), R.drawable.ic_feedback, R.color.beco_white, PorterDuff.Mode.DST_IN),
Util.getCustomDrawableColor(getActivity(), R.drawable.ic_share_app, R.color.beco_white, PorterDuff.Mode.DST_IN),
Util.getCustomDrawableColor(getActivity(), R.drawable.ic_privacy, R.color.beco_white, PorterDuff.Mode.DST_IN),
Util.getCustomDrawableColor(getActivity(), R.drawable.ic_terms, R.color.beco_white, PorterDuff.Mode.DST_IN),
Util.getCustomDrawableColor(getActivity(), R.drawable.ic_faq, R.color.beco_white, PorterDuff.Mode.DST_IN),
Util.getCustomDrawableColor(getActivity(), R.drawable.ic_beco_settings, R.color.beco_white, PorterDuff.Mode.DST_IN),
Util.getCustomDrawableColor(getActivity(), R.drawable.ic_beco_settings, R.color.beco_white, PorterDuff.Mode.DST_IN),
};
holder.textView.setCompoundDrawablesWithIntrinsicBounds(iconLeft[position], null, null, null);
} else {
holder.expandableListView = (ExpandableListView) view.findViewById(R.id.expand_list);
holder.containerList = (LinearLayout) view.findViewById(R.id.container_expandable_list);
holder.expandableListView.setAdapter(new ExpandableListAdapter(context, mHelpLabels.get(position), view));
holder.expandableListView.setOnGroupClickListener((parentExpand, v, groupPosition, id) -> {
setListViewHeight(parentExpand, groupPosition);
return false;
});
}
return view;
}
像这样:
public class Case : BaseEntity
{
public long EmployeeId { get; set; }
public virtual Employee Employee{ get; set; }
我想命名我的属性InitialContact。不是员工。
但是当EF尝试创建数据库时,我收到此错误:
无法确定“Employee”类型的导航属性“Case.InitialContact”所代表的关系。手动配置关系,或从模型中忽略此属性。
我让它像这样工作:
public class Case : BaseEntity
{
public long InitialContactId { get; set; }
public virtual Employee InitialContact { get; set; }
}
主键是我的BaseEntity中的ID。不是EmployeeId。
但我的第二部分是我的问题。
这是我的完整员工POCO:
public class Case : BaseEntity
{
public long InitialContactId { get; set; }
[ForeignKey("Id")]
public virtual Employee InitialContact { get; set; }
public DateTime InitalConsultDate { get; set; }
public Guid AppUserId { get; set; }
public virtual AppUser LerSpecialist { get; set; }
我希望我的员工有很多案例:
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using Hrsa.Core.Generic.Model.Framework.Concrete;
using Microsoft.AspNetCore.Mvc.ModelBinding;
namespace Hrsa.Core.Generic.Model.Lerd
{
public class Employee : BaseEntity
{
[BindNever]
public string Email { get; set; }
[BindNever]
public long OrganizationId { get; set; }
[BindNever]
public string Supervisor { get; set; }
[BindNever]
public string SupervisorEmail { get; set; }
[BindNever]
public string FirstName { get; set; }
[BindNever]
public string LastName { get; set; }
public string Notes { get; set; }
[BindNever]
public long BargainingUnitId { get; set; }
[BindNever]
public long PayPlanId { get; set; }
[BindNever]
public long GradeRankId { get; set; }
[BindNever]
public long PositionTitleId { get; set; }
[BindNever]
public long SeriesId { get; set; }
public bool IsUnionEmployee { get; set; }
public virtual Organization Organization { get; set; }
public virtual BargainingUnit BargainingUnit { get; set; }
public virtual PayPlan PayPlan { get; set; }
public virtual GradeRank GradeRank { get; set; }
public virtual PositionTitle PositionTitle { get; set; }
public virtual Series Series { get; set; }
public virtual ICollection<UnionHours> UnionHours { get; set; }
public virtual ICollection<Case> Cases { get; set; }
[NotMapped]
public string UnionEmployeeYesNo => (IsUnionEmployee) ? "Yes" : "No";
}
}
以下是我完整的案例POCO:
public virtual ICollection<Case> Cases { get; set; }
所以现在我的数据库看起来像这样:
所以我在案例中有我的InitialContactId。
但现在我需要我的案例才能有很多员工。
所以我把它添加到我的Case POCO中:
public class Case : BaseEntity
{
public long InitialContactId { get; set; }
[ForeignKey("Id")]
public virtual Employee InitialContact { get; set; }
public DateTime InitalConsultDate { get; set; }
public Guid AppUserId { get; set; }
public virtual AppUser LerSpecialist { get; set; }
}
现在看起来像这样:
public virtual ICollection<Employee> Employees { get; set; }
}
现在,当我运行它时,我再次收到此错误:
无法确定“Employee”类型的导航属性“Case.InitialContact”所代表的关系。手动配置关系,或从模型中忽略此属性。
我在.Net Core 1中找到了许多关系的这篇文章: http://www.learnentityframeworkcore.com/configuration/many-to-many-relationship-configuration
所以现在我有一个桥查找实体:
public class Case : BaseEntity
{
public long InitialContactId { get; set; }
[ForeignKey("Id")]
public virtual Employee InitialContact { get; set; }
public DateTime InitalConsultDate { get; set; }
public Guid AppUserId { get; set; }
public virtual AppUser LerSpecialist { get; set; }
public virtual ICollection<Employee> Employees { get; set; }
员工POCO:
更改:
public class EmployeeCase
{
[ForeignKey("Id")]
public long EmployeeId { get; set; }
public Employee Employee { get; set; }
[ForeignKey("Id")]
public long CaseId { get; set; }
public Case Case { get; set; }
}
为:
public virtual ICollection<Case> Cases { get; set; }
案例POCO:
更改:
// Mapping - Collection of Cases
public virtual ICollection<EmployeeCase> EmployeeCases { get; set; }
为:
public virtual ICollection<Employee> Employees { get; set; }
在我的AppDbContext
中 // Mapping - Collection of Employees
public virtual ICollection<EmployeeCase> EmployeeCases { get; set; }
现在,当我跑步时,我收到此错误:
Microsoft.EntityFrameworkCore.Relational.dll中发生了'System.Data.SqlClient.SqlException'类型的异常,但未在用户代码中处理
附加信息:在表'EmployeeCase'上引入FOREIGN KEY约束'FK_EmployeeCase_Employees_EmployeeId'可能会导致循环或多个级联路径。指定ON DELETE NO ACTION或ON UPDATE NO ACTION,或修改其他FOREIGN KEY约束。
无法创建约束或索引。查看以前的错误。
最后通过以下代码获得了我想要的表格: Introducing FOREIGN KEY constraint may cause cycles or multiple cascade paths - why?
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
base.OnModelCreating(modelBuilder);
#region Many-to-Many Employees Cases
modelBuilder.Entity<EmployeeCase>()
.HasKey(ec => new { ec.EmployeeId, ec.CaseId });
modelBuilder.Entity<EmployeeCase>()
.HasOne(ec => ec.Employee)
.WithMany(e => e.EmployeeCases)
.HasForeignKey(ec => ec.EmployeeId);
modelBuilder.Entity<EmployeeCase>()
.HasOne(ec => ec.Case)
.WithMany(c => c.EmployeeCases)
.HasForeignKey(ec => ec.CaseId);
#endregion
}
这毕竟不起作用。 重新删除所有内容的删除行为会弄乱我的其他关系,我会收到错误。
我该如何解决这个问题? 这太恶心了。 所以希望我没有去核心。
答案 0 :(得分:0)
实体框架使用约定来猜测如何将C#模型映射到数据库对象。
在您的情况下,您违反了自定义名称的约定,因此您应该解释实体框架如何映射这些内容。
有两种可能的方法:属性和流畅的API。我建议使用后者。
参见&#34;配置不遵守守则第一约定的外键名称&#34;在这里:Entity Framework Fluent API - Relationships
答案 1 :(得分:0)
我已经养成了明确定义我的人际关系的习惯,因为EF并不总能按照我想要的方式获得它们。我想创建一个包含我的实体地图的 Mapping 文件夹。流畅的api非常适用于此,并继承自 EntityTypeConfiguration 。
试试这个。
public class CaseMap : EntityTypeConfiguration<Case>
{
public CaseMap()
{
HasKey(m => m.Id)
HasRequired(m => m.InitialContact)
.WithMany(e => e.Cases)
.HasForeignKey(m => m.InitialContactId);
}
}
几乎忘记了。您需要告诉您的DbContext在哪里找到这些映射。将其添加到您的DbContexts OnModelCreating方法。
modelBuilder.Configurations.AddFromAssembly(typeof(MyContext).Assembly);
答案 2 :(得分:0)
这最终对于EF Core中多对多的层叠删除循环引用起作用了:
// Get rid of Cascading Delete Circular references error.
var type = modelBuilder.Model.GetEntityTypes().Single(t => t.Name == "Hrsa.Core.Generic.Model.Lerd.EmployeeCase");
foreach (var relationship in type.GetForeignKeys())
{
relationship.DeleteBehavior = DeleteBehavior.Restrict;
}
您必须让实体仅代表多对多查找。 并从那里限制DeleteBehavior。