如何在我的EF POCO中将导航属性命名为与其实体名称不同的名称?

时间:2017-03-31 13:44:24

标签: entity-framework asp.net-core-mvc

我有一个名为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”所代表的关系。手动配置关系,或从模型中忽略此属性。

更新1:

我让它像这样工作:

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; }

所以现在我的数据库看起来像这样:

enter image description here

所以我在案例中有我的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”所代表的关系。手动配置关系,或从模型中忽略此属性。

更新2:

我在.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约束。

无法创建约束或索引。查看以前的错误。

更新3:

最后通过以下代码获得了我想要的表格: 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

    }

更新4:

这毕竟不起作用。 重新删除所有内容的删除行为会弄乱我的其他关系,我会收到错误。

我该如何解决这个问题? 这太恶心了。 所以希望我没有去核心。

3 个答案:

答案 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。