实体框架4中的唯一键

Asa*_*f R 19 entity-framework unique-key entity-framework-4

现有数据库模式具有唯一的非主要密钥,以及一些依赖于它们的外键.

是否可以在Entity Framework v4中定义不是主键的唯一键?怎么样?

Eva*_*tti 16

Entity Framework 6.1现在支持使用Data Annotations和Fluent API的唯一身份验证.

数据注释(参考)

public class MyEntityClass
{ 
    [Index(IsUnique = true)]
    [MaxLength(255)] // for code-first implementations
    public string MyUniqueProperty{ get; set; } 
}
Run Code Online (Sandbox Code Playgroud)

Fluent API(参考)

public class MyContext : DbContext
    {
        protected override void OnModelCreating(DbModelBuilder modelBuilder)
        {
            modelBuilder 
                .Entity<MyEntityClass>() 
                .Property(t => t.MyUniqueProperty) 
                .HasMaxLength(255) // for code-first implementations
                .HasColumnAnnotation( 
                    "Index",  
                    new IndexAnnotation(new[] 
                        { 
                            new IndexAttribute("Index") { IsUnique = true } 
                        })));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

您必须应用索引并将unique属性设置为true.默认情况下,根据文档,索引是非唯一的.

此外,您还必须在项目中安装Entity Framework 6.1 NuGet包,以便将新API用于索引.

关于代码优先实现的注意事项:A VARCHAR(MAX)不能是唯一约束的一部分.您必须将最大长度指定为数据注释或Fluent API.


Ken*_*ith 11

另请参阅此MSDN博客文章:http://blogs.msdn.com/b/efdesign/archive/2011/03/09/unique-constraints-in-the-entity-framework.aspx.简而言之,V4不支持这一点,尽管EF团队似乎计划在未来的版本中支持它.

  • 不幸的是,未来版本不会是下一个版本(EF 5.0和.NET 4.5) (6认同)

Mir*_*lad 10

我不久前遇到了同样的问题.

我得到了一个包含几个表格的数据库(见下文).

 public class ClinicDbContext : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<Doctor> Doctors { get; set; }
    public DbSet<Patient> Patients { get; set; }
    public DbSet<Secretary> Secretarys { get; set; }
    public DbSet<Disease> Diseases { get; set; }
    public DbSet<Consultation> Consultations { get; set; }
    public DbSet<Administrator> Administrators { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

Users表的描述如下:

public class User
{
    [Key]
    public Guid UserId { get; set; }

    public string UserName { get; set; }

    public string Password { get; set; }

    public string Name { get; set; }
    public string Surname { get; set; }
    public string IdentityCardNumber { get; set; }
    public string PersonalNumericalCode { get; set; }
    public DateTime DateOfBirth { get; set; }
    public string Address { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

接下来,我被要求确保所有' UserName '属性都是唯一的.由于没有注释,我不得不想办法解决.这是:

首先,我将我的数据库上下文类更改为如下所示:

public class ClinicDbContext : DbContext
{
    public DbSet<User> Users { get; set; }
    public DbSet<Doctor> Doctors { get; set; }
    public DbSet<Patient> Patients { get; set; }
    public DbSet<Secretary> Secretarys { get; set; }
    public DbSet<Disease> Diseases { get; set; }
    public DbSet<Consultation> Consultations { get; set; }
    public DbSet<Administrator> Administrators { get; set; }

    public class Initializer : IDatabaseInitializer<ClinicDbContext>
    {
        public void InitializeDatabase(ClinicDbContext context)
        {
            if (!context.Database.Exists() || !context.Database.CompatibleWithModel(false))
            {
                if (context.Database.Exists())
                {
                    context.Database.Delete();
                }
                context.Database.Create();

                context.Database.ExecuteSqlCommand("CREATE INDEX IX_Users_UserName ON dbo.Users ( UserName )");
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的重要部分是sql命令,它通过在我们所需的列上强制执行唯一索引来改变表 - 在我们的例子中是> UserName.

可以从主类调用此方法,例如:

class Program
{
    static void Main(string[] args)
    {
        Database.SetInitializer<ClinicDbContext>(new ClinicDbContext.Initializer());

        using (var ctx = new ClinicDbContext())
        {
            Console.WriteLine("{0} products exist in the database.", ctx.Users.Count());
        }

        Console.WriteLine("Press any key to exit.");
        Console.ReadKey();
    }
}
Run Code Online (Sandbox Code Playgroud)

尝试运行Program类时发生的最后一个问题如下:表中的列的类型无效,无法用作索引中的键列

为了解决这个问题,我刚刚为UserName属性添加了[MaxLength(250)]注释.

以下是User类最终的外观:

public class User
{
    [Key]
    public Guid UserId { get; set; }

    [MaxLength(250)]
    public string UserName { get; set; }

    public string Password { get; set; }

    public string Name { get; set; }
    public string Surname { get; set; }
    public string IdentityCardNumber { get; set; }
    public string PersonalNumericalCode { get; set; }
    public DateTime DateOfBirth { get; set; }
    public string Address { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

希望它也能解决你的问题!


Asa*_*f R 8

我试过定义下面的表:

  • 订单[Id(主要,身份),ClientName,FriendlyOrderNum(唯一)]
  • OrderItems [Id(主要,身份),FriendlyOrderNum(唯一),ItemName]

从OrderItems.FriendlyOrderNum(Mant)到Orders.FriendlyOrderNum(一个)的外键映射.

如果可以使用唯一的非主键,则以下SSDL应该有效:

<Schema Namespace="EfUkFk_DbModel.Store" Alias="Self" Provider="System.Data.SqlClient" ProviderManifestToken="2008" xmlns:store="http://schemas.microsoft.com/ado/2007/12/edm/EntityStoreSchemaGenerator" xmlns="http://schemas.microsoft.com/ado/2009/02/edm/ssdl">
    <EntityContainer Name="EfUkFk_DbModelStoreContainer">
      <EntitySet Name="OrderItems" EntityType="EfUkFk_DbModel.Store.OrderItems" store:Type="Tables" Schema="dbo" />
      <EntitySet Name="Orders" EntityType="EfUkFk_DbModel.Store.Orders" store:Type="Tables" Schema="dbo" />
    </EntityContainer>
    <EntityType Name="OrderItems">
      <Key>
        <PropertyRef Name="RowId" />
      </Key>
      <Property Name="RowId" Type="bigint" Nullable="false" StoreGeneratedPattern="Identity" />
      <Property Name="OrderNum" Type="char" Nullable="false" MaxLength="5" />
      <Property Name="ItemName" Type="varchar" MaxLength="100" />
    </EntityType>
    <!--Errors Found During Generation:
  warning 6035: The relationship 'FK_OrderItems_Orders' has columns that are not part of the key of the table on the primary side of the relationship. The relationship was excluded.
  -->
    <EntityType Name="Orders">
      <Key>
        <PropertyRef Name="RowId" />
      </Key>
      <Property Name="RowId" Type="bigint" Nullable="false" StoreGeneratedPattern="Identity" />
      <Property Name="ClientName" Type="varchar" MaxLength="100" />
      <Property Name="OrderNum" Type="char" Nullable="false" MaxLength="5" />
    </EntityType>

  <!-- AsafR -->
    <Association Name="FK_OrderItems_Orders">
      <End Role="Orders" Type="EfUkFk_DbModel.Store.Orders" Multiplicity="1">
      </End>
      <End Role="OrderItems" Type="EfUkFk_DbModel.Store.OrderItems" Multiplicity="*" />
      <ReferentialConstraint>
        <Principal Role="Orders">
          <PropertyRef Name="OrderNum" />
        </Principal>
        <Dependent Role="OrderItems">
          <PropertyRef Name="OrderNum" />
        </Dependent>
      </ReferentialConstraint>
    </Association>
  </Schema></edmx:StorageModels>
Run Code Online (Sandbox Code Playgroud)

它没有.也无法在<EntityType>中添加更多<key>元素.

我的结论是EF 4中不支持非主要唯一键.