2014-10-08 11 views
7

Tôi đang sử dụng Khung thực thể 6 và tôi cần cập nhật các thuộc tính của một thực thể.Cập nhật thuộc tính Thực thể tại EF, nơi bất động sản là một thực thể khác

Tôi đã các đối tượng sau:

public class File 
{ 
    public Int32 Id { get; set; } 
    public Byte Data { get; set; } 
    public DateTime Updated { get; set; } 
    public virtual Mime Mime { get; set; } 
} 
public class Mime 
{ 
    public Int32 Id { get; set; } 
    public String Name { get; set; } 
    public virtual ICollection<File> Files { get; set; } 
} 

Sau đó, tôi sử dụng như sau:

_repository.Update<File>(file, x => x.Data, x => x.Mime, x => x.Updated); 

Phương pháp kho được như sau:

public void Update<T>(T entity, 
         params Expression<Func<T, Object>>[] properties) 
         where T : class 
{ 

    _context.Set<T>().Attach(entity); 

    foreach (var property in properties) 
    { 
    MemberExpression expression = 
        property.Body is MemberExpression ? 
        (MemberExpression)property.Body : 
        (MemberExpression)(((UnaryExpression)property.Body) 
                    .Operand); 
    _context.Entry<T>(entity) 
      .Property(expression.Member.Name).IsModified = true; 
    } 
} 

này hoạt động tốt cho Data và Đã cập nhật các thuộc tính nhưng không cho thuộc tính Mime. Tôi gặp lỗi:

The property 'Mime' on type 'File' is not a primitive or complex property. The Property method can only be used with primitive or complex properties. Use the Reference or Collection method.

Có thể thực hiện công việc này và tích hợp nó vào phương pháp lưu trữ của tôi không?

+5

Câu hỏi đầu tiên là: tại sao bạn có phương pháp 'Cập nhật 'phức tạp này? Tại sao bạn không thể để nó theo dõi thay đổi của EF để đánh dấu các thuộc tính như đã sửa đổi? Bức tranh lớn hơn là gì? –

+0

Thực thể Tệp có thuộc tính Dữ liệu có thể là loại lớn vì nó chứa tệp ... Vì vậy, tôi muốn cập nhật một số trường mà không tải dữ liệu vào bộ nhớ. Điều này có nghĩa không? Điều này làm việc khi tôi không có các thực thể liên quan đến nó. –

+0

Bạn nên xem * tách bảng *. –

Trả lời

0

Có, tôi nghĩ rằng có thể được thực hiện. Vấn đề ở đây là tôi không thấy bất kỳ cách nào dễ dàng để kiểm tra bất cứ khi nào một thuộc tính là một phần của bảng hoặc là thuộc tính điều hướng. Do đó rất khó để gọi đúng hành vi.

Nếu bạn quan tâm, hãy xem mã nguồn EF6, InternalEntityEntry.cs ->Property(..) xác thực số lượng lớn xác thực thuộc tính thông qua siêu dữ liệu. Ý tưởng chính là về cơ bản quét mô hình khái niệm của bạn và xác định bất cứ khi nào thuộc tính là thuộc tính điều hướng (ví dụ: nếu thuộc tính dẫn đến một bảng khác), hoặc nếu nó phức tạp/nguyên thủy.

Theo đó, bạn gọi đúng chức năng.

var propertyName = expression.Member.Name;            
var propertyType = __get_property_type__(propertyName); 

if(propertyType==Property || propertyType==Complex) 
{ 
    _context.Entry<T>(entity) 
     .Property(propertyName).IsModified = true; 

    continue; 
} 

if(propertyType==Navigational){ 

    // hm, do we need Attach it first?! 
    // not sure.. have to test first. 
    dynamic underlyingReference = entity.GetType() 
      .GetProperty(propertyName) 
      .GetValue(entity, null); 

    _context.Entry(underlyingReference).State = EntityState.Modified; 
} 

Bắt tại đây phải có __get_property_type__ hoạt động. Có Microsoft.Data.Edm.dll mà hãy để bạn làm việc với mô hình khái niệm, nhưng nó không phải là dễ dàng tôi nghĩ.

Đây là cách làm thế nào EF6 phát hiện nếu chúng ta đang làm việc với tài sản tài liệu tham khảo hay không:

EdmMember member; 
EdmEntityType.Members.TryGetValue(propertyName, false, out member); 

var asNavProperty = member as NavigationProperty; 
// if asNavProperty!=null, we have navigation property. 
-2

100% Gerts điểm. Tôi không thấy lý do gì để tiếp cận vấn đề theo cách của họ. Dù sao, để trả lời câu hỏi. Bạn có câu trả lời khác ở đó. Có tiềm năng hữu ích.

Thiếu thông tin này là:

Cách nhận danh sách các loại được quản lý từ ngữ cảnh.

public static IList<Type> GetContextManagedTypes(DbContext context) { 
     ObjectContext objContext = ((IObjectContextAdapter)context).ObjectContext; 
     MetadataWorkspace workspace = objContext.MetadataWorkspace; 
     IEnumerable<EntityType> managedTypes = workspace.GetItems<EntityType>(DataSpace.OSpace); 

     var typeList = new List<Type>(); 
     foreach (var managedType in managedTypes) { 
      var pocoType = managedType.FullName.GetCoreType(); 
      typeList.Add(pocoType); 
     } 

     return typeList; 
    } 
Các vấn đề liên quan