2011-08-31 33 views
28

Làm cách nào để tìm thuộc tính nào của lớp là khóa chính của thực thể Mã thực thể đầu tiên POCO?Mã khung thực thể trước tiên. Tìm khóa chính

Xin lưu ý rằng đối sánh chuỗi cho Id/tên lớp + "Id" là tùy chọn không hợp lệ. Phải có một số cách để khai thác quy ước được sử dụng bởi Entity Framework và nhận được tài sản quan trọng một cách đáng tin cậy.

Xin cảm ơn trước.

Trả lời

50

Bạn có thể yêu cầu lập bản đồ siêu dữ liệu để có được tên của các thuộc tính quan trọng (có thể có nhiều hơn thì một):

ObjectContext objectContext = ((IObjectContextAdapter)dbContext).ObjectContext; 
ObjectSet<YourEntity> set = objectContext.CreateObjectSet<YourEntity>(); 
IEnumerable<string> keyNames = set.EntitySet.ElementType 
              .KeyMembers 
              .Select(k => k.Name); 

Khi bạn có những cái tên quan trọng bạn có thể sử dụng phản ánh để truy cập giá trị của họ.

Như bạn có thể thấy cách tiếp cận quay trở lại API ObjectContext vì DbContext API chỉ dành cho các tình huống đơn giản mà bạn không bận tâm với các chi tiết như lập bản đồ siêu dữ liệu.

+1

Thx. được đánh dấu là câu trả lời. Tôi muốn bình luận rằng đó là một ý tưởng tốt hơn để thêm một giao diện vào lớp ngữ cảnh của bạn (ví dụ, IYourDataContext) và kế thừa IObjectContextAdapter với IYourDataContext đó. Bằng cách đó bạn không phải bỏ nó. –

+0

Với điều này là 5 tuổi bây giờ, có cách nào để làm điều này mà không phản ánh nặng? Ngữ cảnh của câu hỏi của tôi là một nỗ lực để thực hiện một phương thức Find mà không theo dõi, chẳng hạn như SingleOrDefault() nhưng trong một lớp cơ sở không thể giả định để biết tên khóa của thực thể đó. Cảm ơn các bạn. –

+0

cảm ơn rất nhiều, làm việc như một say mê –

22

Trong trường hợp nó giúp bất cứ ai, tôi cần thiết để có thể làm điều này mà không có sự hiểu biết các loại trước đó (vì vậy tôi không thể dễ dàng làm CreateObjectSet<YourEntity>() vì tôi không biết YourEntity), vì vậy tôi đã có thể thích ứng @Ladislav 's giải pháp như sau:

// variable "type" is a System.Type passed in as a method parameter 
ObjectContext objectContext = ((IObjectContextAdapter)this.context).ObjectContext; 
IEnumerable<string> retval = (IEnumerable<string>)objectContext.MetadataWorkspace 
    .GetType(type.Name, type.Namespace, System.Data.Entity.Core.Metadata.Edm.DataSpace.CSpace) 
    .MetadataProperties 
    .Where(mp => mp.Name == "KeyMembers") 
    .First() 
    .Value; 

có vẻ loại lẻ mà đòi hỏi MetadataWorkspace.GetType chuỗi của tên loại và không gian tên, thay vì một System.Type, nhưng đó là tốt nhất mà tôi có thể tìm thấy.

+0

Thanx, Bạn đã cứu mạng tôi! –

7

Tôi đã gặp sự cố với cả hai phương pháp trên do di sản Bảng Per Loại. phiên bản làm việc của tôi (dựa trên giải pháp @ S'pht'Kr nhưng sử dụng DataSpace.OSpace không DataSpace.CSpace vì lý do này) là dưới đây:

 protected IEnumerable<string> GetKeyPropertyNames() 
     { 
      var objectContext = ((System.Data.Entity.Infrastructure.IObjectContextAdapter) this.Context).ObjectContext; 

      return GetKeyPropertyNames(typeof (TEntity), objectContext.MetadataWorkspace); 
     } 

     private static IEnumerable<string> GetKeyPropertyNames(Type type, MetadataWorkspace workspace) 
     { 
      EdmType edmType; 

      if (workspace.TryGetType(type.Name, type.Namespace, DataSpace.OSpace, out edmType)) 
      { 
       return edmType.MetadataProperties.Where(mp => mp.Name == "KeyMembers") 
        .SelectMany(mp => mp.Value as ReadOnlyMetadataCollection<EdmMember>) 
        .OfType<EdmProperty>().Select(edmProperty => edmProperty.Name); 
      } 

      return null; 
     } 
+0

Tuyệt vời.đã giúp tôi –

9

Trong EF 6.1 có một phương pháp Db() mở rộng mà làm cho dễ dàng hơn này.

Ví dụ:

public static IEnumerable<string> GetPrimaryKeyPropertyNames(DbContext db, Type entityType) 
{ 
    return db.Db(entityType).Pks.Select(x => x.PropertyName); 
} 
+0

Hiệu suất của nó như thế nào? Nặng với phản xạ cơ bản? –

+0

Tôi không có ý tưởng, EntityFramework là kiến ​​thức của tôi dựa trên rất nhiều sự phản ánh để bắt đầu. – angularsen

+0

anjdreas: Điểm tốt. –

2

Giống như người dùng rashleighp, tôi cũng muốn có một biến thể của người sử dụng Ladislav Mrnka của câu trả lời rằng chỉ cần biết loại tại thời gian chạy thay vì cần phải biết loại tại thời gian biên dịch. Cũng giống như người dùng rashleighp, giải pháp của người dùng S'pht'Kr không làm việc cho tôi, nhưng giải pháp của anh ấy đã làm việc. Dưới đây, tôi đóng góp cho cuộc trò chuyện này bằng cách cung cấp một phiên bản đơn giản hơn cho câu trả lời của anh ấy. Tuy nhiên, tôi chỉ biết về giải pháp của người dùng anjdreas và đó là một trong đó tôi sẽ sử dụng.

// variable "type" is a System.Type passed in as a method parameter 
((IObjectContextAdapter)context) 
    .ObjectContext 
    .MetadataWorkspace 
    .GetItem<EntityType>(type.FullName, DataSpace.OSpace) 
    .KeyProperties 
    .Select(p => p.Name); 
Các vấn đề liên quan