带有接口的实体框架代码优先迁移

本文关键字:代码 迁移 框架 实体 接口 | 更新日期: 2023-09-27 18:22:07

我正在尝试使用接口作为属性类型的Attribute/annotations方法来运行EF代码优先迁移。我们已经构建了一个带有接口的完整基础架构,并正在使用这些接口来实现具体的类,并希望实现迁移。EF似乎没有正确地关联外键关系。有什么方法可以纠正这一点吗?

这里有一个例子:

我有一个IStateProvince界面,如下所示:

 public interface IStateProvince
{
    string Abbreviation { get; set; }
    string Name { get; set; }
    ICountry Country { get; set; }
}

我还有一个ICountry接口,如下所示:

public interface ICountry
{
    string Name { get; set; }
    [MaxLength(2)]
    string TwoLetterIsoCode { get; set; }
    [MaxLength(3)]
    string ThreeLetterIsoCode { get; set; }
    int NumericIsoCode { get; set; }
    List<IStateProvince> StateProvinces { get; set; }
}

我创建了如下具体实现:

[Table("TypeData.Country")]
public class Country : BaseSqlEntity, ICountry
{
    [Required, MaxLength(250)]
    public string Name { get; set; }
    [Required]
    public string TwoLetterIsoCode { get; set; }
    [Required]
    public string ThreeLetterIsoCode { get; set; }
    public int NumericIsoCode { get; set; }
    public virtual List<IStateProvince> StateProvinces { get; set; }
}

州省如下:

[Table("TypeData.StateProvince")]
public class StateProvince : BaseSqlEntity, IStateProvince
{
    [Required, MaxLength(3)]
    public string Abbreviation { get; set; }
    [Required, MaxLength(250)]
    public string Name { get; set; }
    public Guid CountryId { get; set; }
    [ForeignKey("CountryId")]
    public virtual ICountry Country { get; set; }
}

您看到的BaseSqlEntity如下:

public class BaseSqlEntity
{
    [Key]
    public Guid Id { get; set; }
    public DateTime DateCreatedUtc { get; set; }
    public DateTime DateModifiedUtc { get; set; }
    public BaseSqlEntity()
    {
        DateCreatedUtc = DateModifiedUtc = DateTime.UtcNow;
        Id = Guid.NewGuid();
    }
}

我在上下文中添加了dbset,如下所示:

public DbSet<Country> Countries { get; set; }
public DbSet<StateProvince> StateProvinces { get; set; }

在运行迁移时,我得到以下内容:

public override void Up()
    {
        CreateTable(
            "TypeData.Country",
            c => new
                {
                    Id = c.Guid(nullable: false),
                    Name = c.String(nullable: false, maxLength: 250),
                    TwoLetterIsoCode = c.String(nullable: false),
                    ThreeLetterIsoCode = c.String(nullable: false),
                    NumericIsoCode = c.Int(nullable: false),
                    DateCreatedUtc = c.DateTime(nullable: false),
                    DateModifiedUtc = c.DateTime(nullable: false),
                })
            .PrimaryKey(t => t.Id);
        CreateTable(
            "TypeData.StateProvince",
            c => new
                {
                    Id = c.Guid(nullable: false),
                    Abbreviation = c.String(nullable: false, maxLength: 3),
                    Name = c.String(nullable: false, maxLength: 250),
                    CountryId = c.Guid(nullable: false),
                    DateCreatedUtc = c.DateTime(nullable: false),
                    DateModifiedUtc = c.DateTime(nullable: false),
                })
            .PrimaryKey(t => t.Id);
    }

正如您将注意到的,没有生成外键关系,因为它无法以某种方式将ICountry与其实施国家关联起来。

如果我将类型从ICountry更改为Country并对接口进行注释,它会很好地工作并正确地生成关系。

有办法绕过这个吗?如有任何帮助,我们将不胜感激。我们已经使用我们喜欢使用的接口构建了大量可重复使用的体系结构,但这似乎是一个阻碍。

带有接口的实体框架代码优先迁移

您仍然可以使用这些接口
只需要在具体类中实现接口属性,如下所示。

[Table("TypeData.Country")]
public class Country : BaseSqlEntity, ICountry
{
    [Required, MaxLength(250)]
    public string Name { get; set; }
    [Required]
    public string TwoLetterIsoCode { get; set; }
    [Required]
    public string ThreeLetterIsoCode { get; set; }
    public int NumericIsoCode { get; set; }
    public virtual List<StateProvince> StateProvinces { get; set; }
    List<IStateProvince> ICountry.StateProvinces
    {
        get
        {
            return StateProvinces.ToList<IStateProvince>();
        }
        set
        {
            StateProvinces = value.ToList().ConvertAll(o => (StateProvince)o);
        }
    }
}

[Table("TypeData.StateProvince")]
public class StateProvince : BaseSqlEntity, IStateProvince
{
    [Required, MaxLength(3)]
    public string Abbreviation { get; set; }
    [Required, MaxLength(250)]
    public string Name { get; set; }
    public Guid CountryId { get; set; }
    [ForeignKey("CountryId")]
    public virtual Country Country { get; set; }
    ICountry IStateProvince.Country
    {
        get
        {
            return Country;
        }
        set
        {
            Country = (Country)value;
        }
    }
}

希望这能解决你的问题。