В существующей схеме БД есть уникальные, не первичные ключи и некоторые внешние ключи, которые полагаются на них.
Можно ли определить уникальные ключи, которые не являются первичными ключами, в Entity Framework v4? Как?
В существующей схеме БД есть уникальные, не первичные ключи и некоторые внешние ключи, которые полагаются на них.
Можно ли определить уникальные ключи, которые не являются первичными ключами, в Entity Framework v4? Как?
Я попытался определить следующие таблицы:
И отображение внешнего ключа из 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>
Это не так. Также нет возможности добавить больше <key> элементов в <EntityType> .
Мое заключение заключается в том, что непервичные уникальные ключи не поддерживают EF 4.
Структура Entity Framework 6.1 теперь поддерживает uniques как с аннотациями данных, так и с Fluent 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 }
})));
}
}
}
Вам нужно применить индекс и установить для свойства unique значение true. По умолчанию индексы не уникальны в соответствии с документацией.
А также вы должны установить пакет Entity Framework 6.1 NuGet в свой проект, чтобы использовать новый API для индексов.
Замечание о реализациях кода: A VARCHAR(MAX)
не может быть частью уникального ограничения. Вы должны указать максимальную длину либо в виде аннотации данных, либо в Fluent API.
См. также сообщение в блоге MSDN: http://blogs.msdn.com/b/efdesign/archive/2011/03/09/unique-constraints-in-the-entity-framework.aspx. Короче говоря, это не поддерживается в V4, хотя у команды EF есть планы поддержать ее в будущих выпусках.
Недавно я столкнулся с одной и той же проблемой.
Мне была предоставлена база данных с несколькими таблицами (см. ниже).
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, которая изменяет таблицу, применяя уникальный индекс в нашем желаемом столбце → Имя пользователя в нашем случае.
Этот метод можно вызвать из основного класса, например:
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();
}
}
Последняя проблема, возникшая при попытке запустить класс Программа, была следующей: столбец в таблице имеет тип, который недопустим для использования в качестве ключевого столбца в индексе
Чтобы решить эту проблему, я просто добавил аннотацию [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; }
}
Надеюсь, что это тоже решит вашу проблему!
Вы также можете использовать проверку DataAnnotations.
Я создал this (UniqueAttribute
) класс, который наследует ValidationAttribute
, а при применении к свойству значения этот столбец будет восстановлен и проверен во время проверки.
Вы можете взять необработанный код из здесь.