2013-03-30 25 views
16

Tôi có ứng dụng sử dụng EF-CodeFirst 5 (dll ver 4.4.0.0, trên .net 4.0).Tôi có thể đọc siêu dữ liệu EF DbContext bằng cách nào?

tôi cần phải có khả năng đọc siêu dữ liệu thực thể, vì vậy mà tôi có thể, cho một loại entry cho có được thông tin sau:

  • mà tính chất là một-nhiều mối quan hệ (các đơn vị tham chiếu)
  • mà tính rất nhiều-một quan hệ (bộ sưu tập của các đơn vị tham khảo hiện tại)
  • cũng đẹp, nhưng không hoàn toàn cần thiết: sản phẩm nào trên rất nhiều-nhiều mối quan hệ (bộ sưu tập của các mối quan hệ)

Tôi có thể nhận được thông tin này bằng cách viết các vòng foreach trên danh sách các thuộc tính và sau đó "nhận ra" chúng bằng cách dựa vào tất cả các tham chiếu là ảo, nhưng tôi cảm thấy đó không phải là cách "thích hợp". Tôi biết rằng EdmxWriter có thể cung cấp thông tin đó ở định dạng xml, nhưng nó thực hiện bằng cách truy cập InternalContext không thể truy cập công khai và tôi muốn trực tiếp nhận danh sách/mảng được đánh máy mạnh mà không sử dụng xml đó. API nào tôi nên sử dụng (nếu có một cho điều này, có vẻ như tôi không thể tìm thấy nó)?

+1

Hiện tại, có kế hoạch cải thiện API siêu dữ liệu: https://entityframework.codeplex.com/workitem/1471 Thêm tại đây: http://romiller.com/2013/09/24/ef-code- đầu tiên-bản đồ-giữa-loại-bảng/ – Colin

Trả lời

25

Gorane, điều này sẽ giúp bạn bắt đầu ...
(Tôi đã không chơi nhiều với nó - phải mất một chút thử nghiệm trong debugger để xem sản phẩm/thông tin và làm thế nào để có được nó)

using (var db = new MyDbContext()) 
{ 
    var objectContext = ((IObjectContextAdapter)db).ObjectContext; 
    var container = objectContext.MetadataWorkspace.GetEntityContainer(objectContext.DefaultContainerName, DataSpace.CSpace); 
    foreach (var set in container.BaseEntitySets) 
    { 
     // set.ElementType. 
     foreach (var metaproperty in set.MetadataProperties) 
     { 
      // metaproperty. 
     } 
    } 

    // ...or... 

    var keyName = objectContext 
     .MetadataWorkspace 
     .GetEntityContainer(objectContext.DefaultContainerName, DataSpace.CSpace) 
     .BaseEntitySets 
     .First(meta => meta.ElementType.Name == "Question") 
     .ElementType 
     .KeyMembers 
     .Select(k => k.Name) 
     .FirstOrDefault(); 
} 

và đặc biệt hơn ...

foreach (var set in container.BaseEntitySets) 
{ 
    var dependents = ((EntitySet)(set)).ForeignKeyDependents; 
    var principals = ((EntitySet)(set)).ForeignKeyPrincipals; 
    var navigationProperties = ((EntityType)(set.ElementType)).NavigationProperties; 
    foreach (var nav in navigationProperties) 
    { 
     // nav.RelationshipType; 
    } 
} 

một số các thuộc tính dường như không được tiếp xúc với 'công chúng', do đó bạn sẽ cần phải sử dụng phản ánh - hoặc tìm một số cách thông minh hơn - nhưng một việc tốt thông tin nằm trong đó.



Và một số thông tin hơn trong những liên kết này ...

How to get first EntityKey Name for an Entity in EF4

How can I extract the database table and column name for a property on an EF4 entity?


EDIT: Sử dụng danh sách các navigationProperties một s khởi điểm, tôi có mọi thứ tôi cần thiết như thế này:

 ManyToManyReferences = navigationProperties.Where(np => 
      np.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many && 
      np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) 
      .Select(np => Extensions.CreateLambdaExpression<TEntity>(np.Name)) 
      .ToList(); 

     OneToManyReferences = navigationProperties.Where(np => 
      (np.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One || 
      np.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne) && 
      np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many) 
      .Select(np => Extensions.CreateLambdaExpression<TEntity>(np.Name)) 
      .ToList(); 

     ManyToOneReferences = navigationProperties.Where(np => 
      np.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many && 
      (np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One || 
      np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.ZeroOrOne)) 
      .Select(np => Extensions.CreateLambdaExpression<TEntity>(np.Name)) 
      .ToList(); 

     OneToOneReferences = navigationProperties.Where(np => 
      np.FromEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One && 
      np.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.One) 
      .Select(np => Extensions.CreateLambdaExpression<TEntity>(np.Name)) 
      .ToList(); 

phương pháp CreateLambdaExpression không phải là lịch sự của tôi, các khoản tín dụng đi đến Jon Skeet, mã được tạo ra với sự giúp đỡ của this answer

Đây là phương pháp CreateLambdaExpression tôi:

public static Expression<Func<TEntity, object>> CreateLambdaExpression<TEntity>(string propertyName) 
{ 
    ParameterExpression parameter = Expression.Parameter(typeof (TEntity), typeof (TEntity).Name); 
    Expression property = Expression.Property(parameter, propertyName); 

    return Expression.Lambda<Func<TEntity, object>>(property, new[] {parameter}); 
} 
+1

Cảm ơn, g này ot tôi bắt đầu, và tôi có những gì tôi cần (không có phản xạ), mở rộng câu trả lời của bạn để hiển thị như thế nào. –

+1

tuyệt vời, cảm ơn bạn - Tôi sẽ giữ điều này trong các liên kết của tôi - tôi đã có một vài cách sử dụng cho điều đó trước đây - nhưng không bao giờ "phức tạp" trong quá nhiều chi tiết, đây là đoạn mã rất hữu ích. Và một câu hỏi hay. – NSGaga

+0

Có vẻ như 'ForeignKeyDependents' và' ForeignKeyPrincipals' được đánh dấu 'internal' trong' EntitySet' cho EF6. –

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