2009-07-13 28 views
9

Tôi đã có một cái gì đó lớp như thế này:Bỏ qua phương pháp trên các loại thực thể với nHibernate

public class Account 
{ 
    public virtual int Id { get; private set; } 
    public virtual string Username { get; set; } 

    [EditorBrowsable(EditorBrowsableState.Never)] 
    public virtual string Password { get; private set; } 

    public void SetPassword(string password){ ... } 
    public bool CheckPassword(string password) { ... } 
} 

tôi đã thiết lập nó theo cách này vì tôi không bao giờ muốn Password sở hữu sử dụng trực tiếp trong mã đó sử dụng loại Account. Bản đồ Tài khoản trông giống như sau:

public class AccountMap : ClassMap<Account> 
{ 
    public AccountMap() 
    { 
     Id(x => x.Id); 
     Map(x => x.Username); 
     Map(x => x.Password); 
    } 
} 

Khi tôi thực sự sử dụng này với NHibernate tôi nhận được một InvalidProxyTypeException

NHibernate.InvalidProxyTypeException: The following types may not be used as proxies: 
    Fringine.Users.Account: method SetPassword should be virtual 
    Fringine.Users.Account: method CheckPassword should be virtual 

Tôi hiểu rằng NHibernate đang cố gắng để tạo ra một lớp proxy để hỗ trợ tải lười biếng và rằng Tôi có thể đánh dấu các phương thức như ảo thêm một Not.LazyLoad() vào bản đồ để giải quyết ngoại lệ. Nhưng - tôi không muốn làm một trong số đó. Tôi muốn hỗ trợ tải chậm nhưng tôi không thấy lý do tại sao những phương pháp đó cần phải là ảo.

Không NHibernate (hoặc Castle nội bộ) đánh giá nội dung của phương pháp để xác định trường nào được sử dụng và tối ưu hóa tải chậm cho các thuộc tính đó? Nếu không, tại sao phương thức này cần phải là ảo nếu tất cả các thuộc tính là và chúng sẽ được tải xuống khi chúng được tham chiếu bởi phương thức.

Có cách nào để loại trừ một số phương pháp nhất định khỏi yêu cầu ảo không?

Trả lời

7

Lý do là bạn có thể truy cập vào các lĩnh vực trong các phương pháp của bạn, mà sẽ không được khởi tạo. Vì vậy, cách dễ nhất là tải nội dung của thực thể trên bất kỳ cuộc gọi nào đến đối tượng (ngoại lệ duy nhất là quyền truy cập vào id, đã có sẵn trong proxy).

Vì vậy, bạn có thể triển khai một cách an toàn các phương pháp của mình như thể không có proxy - với sự cân bằng rằng phương thức cần phải ảo (mà - tôi đồng ý - không hoàn hảo).

Nếu bạn nghĩ rằng đây là vấn đề đối với thiết kế lớp học của bạn, hãy thử di chuyển chức năng này sang một lớp khác (ví dụ: PasswordManager, PasswordValidator, v.v.). Lớp này sẽ tổng hợp Tài khoản hoặc lấy nó làm đối số, vì vậy Tài khoản sẽ chỉ được tải khi lớp này thực sự gọi một trong các thuộc tính của nó.

+0

Tôi không chắc là nó quan trọng nếu tôi truy cập một trường trong các phương thức đó. Khi trường được truy cập thông qua thuộc tính proxy của nó, nó sẽ khởi tạo cá thể. Các thuộc tính/phương thức duy nhất thực sự cần được ảo hóa là các thuộc tính thực sự đại diện cho các cột trong bảng. –

+0

@Paul: Không, bạn hiểu lầm. Bạn * có thể * truy cập các trường * trực tiếp * trong các phương thức của bạn. Không có gì sai với điều đó, bạn không cần phải lo lắng về việc tải chậm trong trường hợp này. Mã trong thực thể của bạn là * luôn luôn * được thực hiện trong một thực thể được khởi tạo hoàn toàn. Điều này làm cho NH minh bạch hơn. Thật hiếm khi có các cá thể thành viên không phụ thuộc vào trạng thái của cá thể, do đó, có một không gian rất hạn chế để tối ưu hóa. –

+0

Ahh, tôi đã hiểu lầm. Việc bảo vệ truy cập trường không có ý nghĩa. –

0

Tôi đã nhận thấy rằng NHibernate chủ yếu dựa vào POCO cho tất cả các thực thể của nó. Đối với tốt hơn hoặc tồi tệ hơn, tôi đã không chạy trên bất kỳ kịch bản mà một người nào đó đã phá vỡ quy ước đó. Davy Brion explains it in great detail here.(Ông tham chiếu quan điểm của bạn rằng, vâng, bạn có thể đánh dấu các lớp học như tải không lười biếng. Nhưng, kể từ nHibernate sau đó sẽ không tạo ra bất kỳ proxy của bạn, bạn đang bị mắc kẹt.)

I don' t biết nếu điều này là hữu ích, nhưng đó là cách Castle hiện nó. Bây giờ (nếu bạn đang sử dụng 2.1) you're able to choose which proxy generator to use, di chuyển đến one of the other choices có thể cho phép bạn tạo proxy theo cách phù hợp với nhu cầu của bạn.

0

Bạn có thể hủy kích hoạt tải chậm ở cấp lớp và kích hoạt nó trên tài sản theo cơ sở tài sản, việc tải xuống thường được sử dụng cho các mối quan hệ thu thập.

public class AccountMap : ClassMap<Account>{   
    public AccountMap() 
    { 
     Not.LazyLoad(); 
     Id(x => x.Id); 
     Map(x => x.Username).LazyLoad(); 
     Map(x => x.Password);   
    } 
} 

Hoặc bạn có thể thử với một lĩnh vực tư nhân và một "lĩnh vực" chiến lược cho nó:

public class AccountMap : ClassMap<Account>{   
    public AccountMap() 
    { 

     Id(x => x.Id); 
     Map(x => x.Username) 
     Map(x => x.Password).Access.AsCamelCaseField();   
    } 
} 

public class AccountMap : ClassMap<Account>{   
    private string password; 
    public string Password{ get; } 
} 
+0

Có điều gì tương tự với Bản đồ (x => x.Method()) .Không.LazyLoad()? –

+0

bạn cũng có thể hủy kích hoạt thế hệ proxy ckeck với thuộc tính này: use_proxy_validator thành false – MatthieuGD

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