2010-04-10 33 views
19

Một lược đồ DB hiện có có các khóa duy nhất, không chính, khóa và một số khóa ngoài dựa vào chúng.Các khóa duy nhất trong khung Entity 4

Có thể xác định các khóa duy nhất không phải là khóa chính, trong khung Entity Framework v4 không? Làm sao?

Trả lời

8

tôi đã cố gắng xác định các bảng sau:

  • Orders [Id (tiểu học, nhận dạng), CLIENTNAME, FriendlyOrderNum (unique)]
  • OrderItems [Id (tiểu học, nhận dạng), FriendlyOrderNum (unique), ItemName]

Và ánh xạ khóa ngoài từ OrderItems.FriendlyOrderNum (Mant) đến Orders.FriendlyOrderNum (một).

Nếu phím phi chính độc đáo có thể xảy ra các SSDL sau nên làm việc:

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

Nó không. Cũng không có khả năng thêm nhiều hơn < khóa > yếu tố trong một <EntityType>.

Kết luận của tôi là chìa khóa độc đáo phi chính không được hỗ trợ trong EF 4.

11

Xem thêm này trên blog MSDN bài: http://blogs.msdn.com/b/efdesign/archive/2011/03/09/unique-constraints-in-the-entity-framework.aspx. Tóm lại, điều này không được hỗ trợ trong V4, mặc dù nhóm EF dường như có kế hoạch hỗ trợ nó trong các bản phát hành trong tương lai.

+0

Thx cho liên kết, đó là những gì tôi đang tìm kiếm. –

+6

Thật không may là bản phát hành trong tương lai sẽ không phải là bản phát hành tiếp theo (EF 5.0 và .NET 4.5) –

3

Bạn cũng có thể sử dụng tính năng xác thực DataAnnotations.

Tôi đã tạo lớp this (UniqueAttribute), kế thừa ValidationAttribute và khi được áp dụng cho thuộc tính, các giá trị của cột đó sẽ được truy xuất và xác thực trong khi xác thực.

Bạn có thể lấy mã thô từ here.

+1

Thuộc tính này có hoạt động cho kết hợp cột không? –

+0

Thậm chí không có trong EF6: ( – eka

10

Tôi đã gặp vấn đề tương tự cách đây không lâu.

Tôi được cung cấp một cơ sở dữ liệu với một vài bảng (xem bên dưới).

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

Bảng Người dùng đã được mô tả như thế này:

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

Tiếp theo, tôi đã được yêu cầu để đảm bảo rằng tất cả các 'UserName' thuộc tính sẽ là duy nhất. Vì không có chú thích cho điều đó, tôi phải tìm ra một công việc xung quanh. Và ở đây nó là:

Đầu tiên, tôi đã thay đổi lớp bối cảnh cơ sở dữ liệu của tôi trông như thế này:

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

Phần quan trọng từ bên trên là lệnh sql mà làm thay đổi bảng bằng cách thực thi một độc đáo chỉ mục trên cột mong muốn của chúng tôi -> UserName trong trường hợp của chúng tôi.

Phương pháp này có thể được gọi từ những lớp học chính ví dụ:

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

Vấn đề cuối cùng, mà xảy ra khi cố gắng chạy Chương trình lớp là như sau: cột trong bảng thuộc loại không hợp lệ để sử dụng làm cột khóa trong chỉ mục

Để giải quyết vấn đề này, tôi chỉ cần thêm [MaxLength (250)] chú thích cho thuộc tính UserName.

Sau đây là cách lớp người dùng trông cuối cùng:

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

Hy vọng nó sẽ giải quyết vấn đề của bạn quá!

16

Khuôn khổ thực thể 6.1 hiện hỗ trợ duy nhất với cả Chú thích dữ liệu và API lưu loát.

dữ liệu Chú thích (Reference)

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

thạo API (Reference)

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

Bạn cần phải áp dụng một chỉ mục và thiết lập thuộc tính độc đáo là true. Theo mặc định, các chỉ mục không phải là duy nhất theo tài liệu.

Và bạn cũng phải cài đặt gói NuGet Entity Framework 6.1 trong dự án của mình để sử dụng API mới cho các chỉ mục.

Lưu ý về triển khai mã lần đầu: A VARCHAR(MAX) không thể là một phần của ràng buộc duy nhất. Bạn phải chỉ định độ dài tối đa hoặc là Chú thích dữ liệu hoặc trong API thông thạo.

+0

Điều này biên dịch cho tôi, nhưng tôi nhận được một lỗi thời gian chạy mà 'Cột' Email 'trong bảng' dbo.Users 'là loại không hợp lệ để sử dụng làm cột khóa trong chỉ mục.' 'Email' là một chuỗi công khai, giống như' MyUniqueProperty'. – djs

+0

Nó hoạt động tốt ở đây, và tôi đã thực hiện nhiều nỗ lực để tái tạo lỗi của bạn, nhưng tôi không thể. Bạn mở một câu hỏi mới cho tất cả các chi tiết liên quan, bao gồm Phiên bản EF và dấu vết ngăn xếp đầy đủ và lớp học của bạn? Vui lòng thêm nhận xét ở đây với liên kết để tôi có thể điều tra tx! – BonanzaOne

+1

Vấn đề của tôi là vì tôi đang sử dụng triển khai mã đầu tiên, tạo cột 'Email' là ' NVARCHAR (MAX) 'theo mặc định.Tôi đã thực hiện một chỉnh sửa để giải quyết trường hợp này.Giải pháp của bạn hoạt động tốt cho tôi ngay bây giờ! – djs

Các vấn đề liên quan