2008-11-19 36 views
13

Tôi biết có sự kiện AssociationChanged, tuy nhiên, sự kiện này sẽ kích hoạt sau khi kết hợp được thực hiện. Không có sự kiện AssociationChanging. Vì vậy, nếu tôi muốn ném một ngoại lệ cho một số lý do xác nhận, làm thế nào để tôi làm điều này và lấy lại giá trị ban đầu của tôi?Entity Framework Xác nhận & sử dụng

Ngoài ra, tôi muốn giá trị mặc định cho pháp nhân của mình dựa trên thông tin từ các thực thể khác nhưng chỉ thực hiện việc này khi tôi biết quyền truy cập được chèn vào cơ sở dữ liệu. Làm thế nào để tôi biết sự khác biệt giữa điều đó và đối tượng đang được instanced bởi vì nó sắp được phổ biến dựa trên dữ liệu hiện có? Tôi có nên biết không? Đó có phải là logic kinh doanh được xem xét nên nằm ngoài logic kinh doanh thực thể của tôi không?

Nếu đúng như vậy, thì tôi có nên thiết kế các lớp điều khiển để bọc tất cả các thực thể này không? Mối quan tâm của tôi là nếu tôi phân phối lại thực thể, tôi muốn khách hàng truy cập vào các thuộc tính, nhưng tôi muốn giữ quyền kiểm soát chặt chẽ đối với các xác thực về cách chúng được đặt, mặc định, v.v. mà là bên ngoài xác nhận một phần của lớp enity của tôi, phải không?

BTW, tôi nhìn vào EFPocoAdapter và cho cuộc sống của tôi không thể xác định cách điền các danh sách từ bên trong lớp POCO của tôi ... bất cứ ai biết cách tôi đến ngữ cảnh từ một lớp EFPoco?

Trả lời

0

Liên quan đến câu hỏi đầu tiên của bạn, tôi sẽ chỉ thực hiện các thay đổi đối với các liên kết dưới dạng logic nghiệp vụ. Ví dụ, nếu bạn thêm một lớp giáo viên với nhiều sinh viên, không thêm sinh viên như

aTeacher.Students.Add(new Student) 

thay vào đó, tạo ra một phương pháp addStudent

public Student AddNewStudent(string name, string studentID) 
{ 

    Student s = new Student(name, studentID); 
    s.Teacher = this; // changes the association 
    return s; 
} 

Bằng cách đó bạn có thể kiểm soát đầy đủ về khi hiệp hội đang thay đổi. Tất nhiên điều gì ngăn cản một lập trình viên khác thêm trực tiếp sinh viên? Về phía Sinh viên, bạn có thể đặt giáo viên setter thành private (và thay đổi constructor để chấp nhận một giáo viên hoặc tương tự). Về phía giáo viên, làm thế nào để làm cho bộ sưu tập Học sinh không thể chèn được? Tôi không chắc chắn ... có thể biến nó thành một bộ sưu tập tùy chỉnh không chấp nhận sự chèn.

Liên quan đến phần thứ hai của câu hỏi, bạn có thể sử dụng các sự kiện OnVarNameChanging. Nếu EntityState là 'Mới' thì bạn có thể áp dụng logic của bạn để tìm nạp các giá trị thực.

Ngoài ra còn có một sự kiện xảy ra khi bạn lưu thay đổi (OnSavingChanges?) Mà bạn có thể sử dụng để xác định đối tượng nào mới và đặt một số giá trị.

Nhưng có lẽ giải pháp đơn giản nhất là luôn đặt giá trị mặc định trong hàm tạo và chúng sẽ bị ghi đè nếu dữ liệu được tải từ DB.

Chúc may mắn

0

Tạo một nhà máy sản xuất các trường hợp cho bạn tùy thuộc vào nhu cầu của bạn như:

getStudent(String studentName, long studentId, Teacher teacher) { 
    return new Student(studentName, studentId); 
} 

getStudentForDBInseration(String studentName, long studentId, Teacher teacher) { 
    Student student = getStudent(studentName, studentId); 
    student = teacher; 
    //some entity frameworks need the student to be in the teachers student list 
    //so you might need to add the student to the teachers student list 
    teacher.addStudent(student); 
} 
0

Đó là một thiếu nghiêm trọng không có một AssociationChanging (được thừa kế từ CancelEventArgs) sự kiện.

Nó làm tôi bực mình cũng rất nhiều, do đó tôi đã báo cáo này cho Microsoft Connect Please vote here!

Và BTW, tôi cũng nghĩ rằng đây cũng là ngu ngốc rằng PropertyChangingEventArgs không kế thừa CancelEventArgs, kể từ khi hủy bỏ với một ngoại lệ là không phải lúc nào cũng là giải pháp thanh lịch, bên cạnh đó, việc ném ngoại lệ tốn kém hơn so với việc gọi OnPropertyChangingEvent rồi kiểm tra e.Cancel đã trả về, vì vậy nó có chi phí ít hơn là tăng PropertyChangingEvent, mà bạn vẫn gọi cả hai.
Ngoài ra, một ngoại lệ có thể được ném vào trình xử lý thay vì đánh dấu e.Cancel là đúng, đối với những người khăng khăng đi theo cách Ngoại lệ. Vote Here.

+1

PropertyChangingEventArgs không có liên quan đến CancelEventArgs. Họ có thời gian họ cần phải được sử dụng riêng cho các mục đích khác nhau. Để buộc thừa kế sẽ gây ra biến chứng không cần thiết và thất vọng (kết nối chặt chẽ chúng với nhau). Có PropertyChangingEvent và PropertyChangedEvent, và tôi tin rằng chúng thỏa mãn các chức năng mà bạn mong muốn mà không cần thay đổi đối với chúng (chưa kể, điều đó sẽ phá vỡ .NET 1.1 thành .NET 4.0 tương thích). – TamusJRoyce

+0

@TamusJRoyce, OK, tôi đồng ý, không nên kế thừa từ 'CancelEventArgs', nhưng điều tôi cần làm là yêu cầu khác của tôi, cung cấp giá trị ứng cử viên (cách dễ dàng để lấy nó là nhận các thuộc tính phương thức hiện tại lượng chi phí hiệu suất). – Shimmy

0

Để trả lời một phần câu hỏi của bạn hoặc giải thích về câu trả lời của ADB, bạn có thể sử dụng ObjectStateManager.GetObjectStateEntry để tìm trạng thái của các thực thể và viết logic mặc định tùy chỉnh của bạn.

SaveChanges là phương pháp trong ngữ cảnh mà bạn có thể sử dụng hoặc SavingChanges là sự kiện xảy ra trước khi SaveChanges được gọi.

Bạn có thể ghi đè lên SaveChanges và base.SaveChanges chỉ gọi nếu bạn không muốn hủy bỏ việc thay đổi

Ngoài ra còn có một sự kiện ObjectMaterialized cho bối cảnh.

Giữa hai bạn có thể dính vào tất cả các xác nhận của bạn và mã tạo tại một địa điểm, trong đó có thể thích hợp nếu họ rất phức tạp và bao gồm giá trị của các đối tượng khác vv ..

2

Đây là trả lời một bình luận tôi rời . Hy vọng điều này sẽ trả lời câu hỏi của bạn, Shimmy. Chỉ cần bình luận và tôi sẽ rút ngắn hoặc xóa nó nếu nó không trả lời câu hỏi của bạn.

Bạn sẽ cần cả hai giao diện INotifyPropertyChanging và INotifyPropertyChanged sẽ được triển khai trên lớp của bạn (trừ khi nó giống như đối tượng khung thực thể, mà tôi tin rằng thực hiện các nội bộ này).

Và trước khi bạn đặt giá trị cho thuộc tính này, bạn sẽ cần tăng sự kiện NotifyPropertyChanging.PropertyChanging, sử dụng tên thuộc tính trong hàm tạo PropertyChangingEventArgs.

Và sau khi bạn đặt giá trị này, bạn cần phải nâng cao sự kiện NofityPropertyChanged.PropertyChanged, một lần nữa bằng cách sử dụng tên của thuộc tính này đang được nâng lên trong constructor PropertyChangedEventArgs.

Sau đó, bạn phải xử lý các sự kiện PropertyChanging và PropertyChanged. Trong sự kiện PropertyChanging, bạn cần phải cache giá trị. Trong sự kiện PropertyChanged, bạn có thể so sánh và ném một ngoại lệ.

Để nhận thuộc tính từ PropertyChanging/PropertyChanged event args, bạn cần phải sử dụng sự phản hồi.

// PropertyName is the key, and the PropertyValue is the value. 
Dictionary <string, object> propertyDict = new Dictionary<object, object>(); 

    // Convert this function prototype to C# from VBNet. I like how Handles is descriptive. 
    Public Sub PropertyChanging(sender As object, e As PropertyChangingEventArgs) Handles Foo.PropertyChanging 
    { 
     if (sender == null || preventRecursion) 
     { 
     return; 
     } // End if 

     Type senderType = sender.GetType(); 
     PropertyInfo info = senderType.GetProperty(e.PropertyName); 
     object propertyValue = info.GetValue(sender, null); 

     // Change this so it checks if e.PropertyName already exists. 
     propertyDict.Add(e.PropertyName, propertyValue); 
    } // End PropertyChanging() Event 

    // Convert this function prototype to C# from VBNet. I like how Handles is descriptive. 
    Public Sub PropertyChanged(sender As object, e As PropertyChangedEventArgs) Handles Foo.PropertyChanged 
    { 
     if (sender == null || preventRecursion) 
     { 
     return; 
     } // End if 

     Type senderType = sender.GetType(); 
     PropertyInfo info = senderType.GetProperty(e.PropertyName); 
     object propertyValue = info.GetValue(sender, null); 

     // Change this so it makes sure e.PropertyName exists. 
     object oldValue = propertyDict(e.PropertyName); 
     object newValue = propertyValue; 

     // No longer needed. 
     propertyDict.Remove(e.PropertyName); 

     if (/* some condition */) 
     { 
     try { 
      preventRecursion = true; 
      info.SetValue(oldValue, null); 
      Throw New Exception(); 
     } finally { 
      preventRecursion = false; 
     } // End try 
     } // End if 
    } // End PropertyChanging() Event 

Lưu ý cách tôi đang sử dụng PreventRecursion, một boolean tôi quên thêm ở trên các phương pháp này là gì? Khi bạn đặt lại thuộc tính về giá trị trước đó của nó, các sự kiện này sẽ bị thu hồi.

tl; dr

Bây giờ bạn có thể lấy được một sự kiện duy nhất mà kế thừa từ INotifyPropertyChanged, nhưng sử dụng một cuộc tranh cãi mà giữ một đối tượng đại diện cho các giá trị trước đó cũng như Tên thuộc tính.Và điều đó sẽ làm giảm số lượng sự kiện bị sa thải xuống một, có chức năng tương tự và có khả năng tương thích ngược với INotifyPropertyChanged. Nhưng nếu bạn muốn xử lý bất cứ điều gì trước khi bất động sản được thiết lập (nói thuộc tính có thay đổi không thể đảo ngược hoặc bạn cần phải thiết lập các thuộc tính khác trước khi thiết lập biến đó, nếu không ngoại lệ sẽ bị ném), bạn sẽ không thể làm việc đó đi.

Nhìn chung, phương pháp này là một cách rất cũ để làm việc. Tôi sẽ nhận câu trả lời của Poker Villian và có thể nhập dữ liệu không hợp lệ. Nhưng không cho phép lưu vào cơ sở dữ liệu.

Khuôn khổ thực thể có một số mã tuyệt vời để xác thực. Bạn thêm xác thực vào các thuộc tính của bạn thông qua các thuộc tính. Và sau đó nó sẽ chăm sóc công việc xử lý các thuộc tính đó. Sau đó, bạn có thể tạo một thuộc tính được gọi là IsValid, gọi là xác nhận hợp lệ khung thực thể Entity Framework. Nó cũng phân biệt cả hai lỗi trường (như nhập sai ký tự hoặc có chuỗi quá dài) và lỗi lớp (như thiếu dữ liệu hoặc khóa xung đột).

Sau đó, bạn có thể liên kết IsValid để kiểm soát xác thực và chúng sẽ hiển thị bong bóng màu đỏ khi dữ liệu không hợp lệ được nhập. Hoặc bạn chỉ có thể thực hiện xác thực IsValid. Nhưng nếu IsValid là sai, sự kiện SaveChanges sẽ cần phải hủy lưu.

btw. Mã được cung cấp sẽ không biên dịch và chỉ là mã giả (trộn vb và C#). Nhưng tôi tin rằng nó mô tả nhiều hơn C# một mình - cho thấy chính xác những gì đang được xử lý.

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