Сначала код EF — составной ключ

У меня есть устаревшая база данных с двумя столбцами, и я хочу сопоставить их как 1 идентификатор, возможно ли это?

Например

    public class Product
{ 
public string ProductID {get;set;}
public string ShortDescription {get;set;}
public string UserName {get;set;}
}

тогда мой Modelbinder выглядит так

modelBinder.Entity<Product>().
HasKey(p=>p.ProductID)
.MapSingle(product =>
new {
 colShotDesc = product.ShortDescription,
 colUser = product.UserName
}
).ToTable("Products");

Мне нужно было бы что-то вроде ProductID = ShortDescription + UserName в сопоставлении... потому что эти два столбца имеют уникальное ключевое ограничение...

Не знаю, имеет ли это смысл, но любые предложения были бы замечательными... Пожалуйста, не спрашивайте о дизайне базы данных => это так, как есть и не должно меняться... вот почему я подумал, что EF code-first может помогите мне (надеюсь скрестить пальцы)... потому что похоже, что БД не имеет pk, определяющего только уникальные ключевые ограничения...

в любом случае ... помощь была бы потрясающей ..


person server info    schedule 03.08.2010    source источник


Ответы (2)


Похоже, вам нужен сложный тип И вы хотите, чтобы сложный тип распознавался как ключ, используя соглашение о добавлении идентификатора в конце имени свойства.

На данный момент EF CF не может этого сделать.

Вы можете сообщить EF CF о составном ключе с помощью атрибута Key или FluentAPI.

Аннотация данных:

public class Product 
{  
  [Key, Column(Order=0)]
  public string ShortDescription {get;set;} 
  [Key, Column(Order=1)]
  public string UserName {get;set;} 
}

Свободный API:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  modelBuilder.Entity<Product>()
               .HasKey(p=> new{p.ShortDescription, p.UserName});
}

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

public class Product 
{  
  public ProductID Key {get;set;}
}

public class ProductID 
{
  public string ShortDescription {get;set;} 
  public string UserName {get;set;} 
}

Затем, чтобы сопоставить его с помощью Fluent API:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
  modelBuilder.ComplexType<ProductID>()
               .Property(p=>p.ShortDescription)
               .HasColumnName("ShortDescription")
               .Property(p=>p.UserName)
               .HasColumnName("UserName");
}

Или, если вы хотите использовать аннотации данных:

[ComplexType]
public class ProductID
{
  [Column("ShortDescription")]
  public string ShortDescription {get;set;} 
  [Column("UserName")]
  public string UserName {get;set;} 
}

Вы должны указать имена столбцов, иначе конфигурация будет предполагать, что имена столбцов — ProductID_ShortDescription....

Еще немного информации о сложных типах.

person Kevin LaBranche    schedule 16.04.2011

На самом деле вы хотите сопоставить одно концептуальное свойство с парой столбцов хранилища. Есть код, который будет объединять значения из столбцов в свойство, пока все хорошо.
Но давайте представим себе процесс добавления нового объекта в контекст. Итак, мы установили значение свойства. Как EF должен знать правило записи значения этого свойства в оба столбца?
Не уверен, что этот сценарий можно реализовать.

person Devart    schedule 04.08.2010
comment
Да, я согласен, что это не так чисто, но это БД, с которой я сталкиваюсь. Поскольку два столбца имеют уникальное ограничение на уровне базы данных, следует убедиться, что они будут заданы. Я также работаю с проверкой, чтобы убедиться, что они установлены. Я хочу, чтобы мое решение в коде было немного чище, поэтому я ищу составной ProductID. Как я могу собрать свои конкатенированные поля в code-first? - person server info; 05.08.2010