Уникальные ключи в Entity Framework 4 - PullRequest
19 голосов
/ 11 апреля 2010

Существующая схема БД имеет уникальные, неосновные, ключи и некоторые внешние ключи, которые на них полагаются.

Можно ли определить уникальные ключи, которые не являются первичными ключами, в Entity Framework v4? Как?

Ответы [ 5 ]

16 голосов
/ 30 апреля 2014

Entity Framework 6.1 теперь поддерживает уникальные приложения с аннотациями данных и свободно используемым API.

Аннотации данных ( Ссылка )

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

Свободный 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 } 
                        })));
        }
    }
}

Вы должны применить индекс и установить для уникального свойства значение true. По умолчанию индексы не являются уникальными согласно документации.

А также вы должны установить пакет NuGet Entity Framework 6.1 в свой проект, чтобы использовать новый API для индексов.

Примечание о реализации кода: A VARCHAR(MAX) не может быть частью уникального ограничения. Вы должны указать максимальную длину в качестве аннотации данных или в Fluent API.

11 голосов
/ 05 апреля 2011

См. Также это сообщение в блоге MSDN: http://blogs.msdn.com/b/efdesign/archive/2011/03/09/unique-constraints-in-the-entity-framework.aspx. Вкратце, это не поддерживается в V4, хотя команда EF, похоже, планирует поддержать его в будущих выпусках.

10 голосов
/ 11 мая 2013

Я столкнулся с той же проблемой не так давно.

Мне дали базу данных с несколькими таблицами (см. Ниже).

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

Таблица 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; }
}

Далее меня попросили убедиться, что все атрибуты ' 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 )");
            }
        }
    }
}

Важной частью сверху является команда 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();
    }
}

Последняя проблема, возникшая при попытке запустить класс Program , была следующей: столбец в таблице имеет недопустимый тип использовать в качестве ключевого столбца в индексе

Чтобы решить эту проблему, я просто добавил [MaxLength (250)] для атрибута UserName.

Вот как выглядит класс 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; }
}

Надеюсь, это тоже решит вашу проблему!

8 голосов
/ 13 апреля 2010

Я попытался определить следующие таблицы:

  • Заказы [Id (основной, идентификационный), ClientName, FriendlyOrderNum (уникальный)]
  • OrderItems [Id (основной, идентификатор), FriendlyOrderNum (уникальный), ItemName]

И отображение внешнего ключа из OrderItems.FriendlyOrderNum (Mant) в Orders.FriendlyOrderNum (one).

Если возможны уникальные неосновные ключи, должен работать следующий 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>

Это не так. Также нет возможности добавить больше элементов в .

Мой вывод таков: неосновные уникальные ключи не поддерживаются в EF 4.

3 голосов
/ 14 апреля 2013

Вы также можете использовать валидацию DataAnnotations.

Я создал этот (UniqueAttribute) класс, который наследует ValidationAttribute, и при применении к свойству значения этого столбца будут получены и проверены во время проверки.

Вы можете получить необработанный код из здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...