2011-08-25 19 views
9

với Entity Framework Code-Đầu tiên tôi phải có tất cả các thuộc tính công khai để tạo cơ sở dữ liệu, điều này có nghĩa là sử dụng phương pháp Entity Framework Code-First Tôi buộc phải có một anemic domain trộn với một mô hình phong phú? Bởi vì các thuộc tính không cần phải được công khai, phải được.Sử dụng Mã khung pháp nhân-đầu tiên tôi được yêu cầu phải có mô hình thiếu máu tên miền của mình?

Ví dụ:

Sử dụng một mô hình phong phú, này trong Entity Framework sẽ không làm việc:

public class Car 
{ 
    private int _actualPosition; 

    public void Accelerate() 
    { 
     this._actualPosition += 10; 
    } 
} 

Để làm việc chúng ta cần phải thực hiện _actualPosition công cộng:

public class Car 
{ 
    public int ActualPosition { get; set; } 

    public void Accelerate() 
    { 
     this.ActualPosition += 10; 
    } 
} 

Bây giờ IMO thực thể là xấu xí, bởi vì tôi có một phương thức thêm + 10 trong thuộc tính và công khai nó cùng một lúc, tôi không muốn pr đó operty được công khai.

Một Ví dụ:

Hãy tưởng tượng tôi muốn có một mối quan hệ nhiều-nhiều nhưng với chỉ có một cách như:

public class User 
{ 
    public long Id { get; set; } 

    public string Name { get; set; } 

    public IList<Role> Roles { get; set; } 
} 

public class Role 
{ 
    public long Id { get; set; } 

    public string Name { get; set; } 
} 

Làm thế nào tôi làm một mối quan hệ nhiều-nhiều với mô hình đó? Theo hiểu biết của tôi không có cách nào tôi sẽ phải làm một mối quan hệ hai chiều:

public class User 
{ 
    public long Id { get; set; } 

    public string Name { get; set; } 

    public IList<Role> Roles { get; set; } 
} 

public class Role 
{ 
    public long Id { get; set; } 

    public string Name { get; set; } 

    public IList<User> Users { get; set; } 
} 

Với mô hình này, tôi sẽ có thể làm cho nhiều-nhiều mối quan hệ:

modelBuilder.Entity<User>() 
       .HasMany(x => x.Roles) 
       .WithMany(y => y.Users); 

tôi đúng không? Nếu có, Entity Framework không làm hài lòng tôi.

Các "Một ví dụ" làm việc với câu trả lời của @Slauma:

modelBuilder.Entity<User>() 
      .HasMany(x => x.Roles) 
      .WithMany() 
      .Map(a => 
      { 
       a.MapLeftKey("UserId"); 
       a.MapRightKey("RoleId"); 
       a.ToTable("UserRoles"); 
      }); 
+0

Bạn chắc chắn không cần tài sản công cộng tại EF EDMX, vì vậy tôi muốn ngạc nhiên nếu bạn đã làm cho mã EF đầu tiên. Có thực sự không phải là một chú thích hoặc một cái gì đó bạn có thể sử dụng để xác định các thuộc tính mà bạn muốn? Tôi nghĩ rằng bạn chắc chắn cần accessors, mặc dù. Người truy cập được bảo vệ hoặc nội bộ có hoạt động không? (Ban đầu tôi nghĩ rằng riêng tư nhưng tôi nghi ngờ nó cần được bảo vệ ít nhất.) – Rup

+2

@Rup: Không có chú thích nào. Các thuộc tính không phải là công khai nhưng chúng phải được hiển thị cho ngữ cảnh và ánh xạ EF. –

+0

@Ladislav Bạn có đồng ý với EF trong trường hợp đó không? –

Trả lời

1

ngắn Trả lời: Trừ khuôn khổ hỗ trợ nó, bạn đang bị mắc kẹt cố gắng để mứt quá nhiều vào lớp này nếu bạn cố gắng với cả hai quy tắc kinh doanh và tài sản công cộng.

dài trả lời: Tôi đã từng sử dụng một hệ thống rất như thế này, và về cơ bản tôi đi đến nhận thức rằng cách tốt nhất để thử nghiệm và đóng gói là để bọc lớp này với lớp miền thật của tôi.

public class Car 
{ 
    private CarPersistence _carPersistence; 

    public void Accelerate() 
    { 
     this._carPersistence.ActualPosition += 10; 
    } 

    public Car (CarPersistence car) { 
     _carPersistence = car; 
    } 
} 

public class CarPersistence 
{ 
    public int ActualPosition; 
} 

Khi tôi đã làm điều này trước đây, tôi đã có thể sau đó có cấp độ thấp hơn Persistence lớp học của tôi thực hiện một giao diện mà có thể được sử dụng bởi các xét nghiệm của tôi để tiêm vào lớp kinh doanh để thử nghiệm đơn giản mà không phải nói chuyện với kho dữ liệu.

Một hệ thống như thế này, với các lớp kinh doanh của bạn trên một "lớp" và các lớp kiên trì của bạn trên một "lớp" khác, bạn có thể dễ dàng có mối quan hệ một-nhiều, nó chỉ phải được xây dựng vào bất cứ điều gì xây dựng doanh nghiệp của bạn lớp học ra khỏi lớp học kiên trì:

public class User 
{ 
    private UserPersistence _user; 
    private IList<Persistence> _roles; 

    public User (UserPersistence user, IList<Persistence> roles) { 
     _user = user; 
     _roles = roles; 
    } 
} 

Xin lỗi, cú pháp có thể không được hoàn hảo, đó là tốt nhất mà tôi có thể nhớ nó chuyển ngữ từ VB sang C#;)

1

bạn có thể thiết lập của bạn Car Entity như thế này:

public class Car 
{ 
    public int ActualPosition { get; private set; } 

    public void Accelerate() 
    { 
     this.ActualPosition += 10; 
    } 
} 

Sửa đổi lực lượng này của thuộc tính ActualPosition để sử dụng phương pháp chuyên ngành Accelerate. Tác dụng phụ của việc sử dụng kiểu này là phương pháp Accelerate của bạn không thể kiểm tra được.

Bạn cũng có thể thiết lập nó như thế này:

public class Car 
{ 
    protected int ActualPosition { get; set; } 

    public void Accelerate() 
    { 
     this.ActualPosition += 10; 
    } 
} 

Tuy nhiên phương pháp này là không trực tiếp kiểm chứng mà không sử dụng phản ánh.

0

Có, mã bạn đã đăng là Anemic Model. Hơn nữa, tôi thậm chí sẽ không gọi nó là một mã định hướng đối tượng thích hợp. Đơn giản là không có đóng gói và các đối tượng chỉ là một thùng chứa dữ liệu. Có vẻ như ORM lựa chọn của bạn đang hạn chế lựa chọn triển khai tên miền của bạn. Đối với những gì nó có giá trị, NHibernate cho phép bạn ánh xạ các trường trực tiếp (ngay cả khi các trường này là chỉ đọc). Nó không yêu cầu các đối tượng có các thuộc tính. Ví dụ:

public class Car { 

    private int _position; 

    public void Accelerate() { 
     _position += 10; 
    } 
} 

có thể được ánh xạ như:

<class name="Car" table="Cars" > 
    ... 
    <property name="_position" column="Position" /> 
    ... 
</class> 
+0

Vâng, tôi biết NH cho phép điều này, vì vậy tôi ngạc nhiên vì sao Khung pháp nhân không đưa ra tuyên bố tương tự. –

3

của bạn "Một ví dụ" là không đúng. Bạn không bị buộc phải phơi bày cả hai đầu của một mối quan hệ như các thuộc tính trong các lớp mô hình của bạn. Trong ví dụ của bạn, bạn có thể loại bỏ public IList<User> Users { get; set; } từ lớp Role của bạn và xác định việc lập bản đồ như vậy:

modelBuilder.Entity<User>() 
      .HasMany(x => x.Roles) 
      .WithMany() 
      .Map(a => 
      { 
       a.MapLeftKey("UserId"); 
       a.MapRightKey("RoleId"); 
       a.ToTable("UserRoles"); 
      }); 

Đây là trường hợp còn cho các mối quan hệ một-nhiều. Luôn luôn có một quá tải With... quá tải, WithMany(), WithRequired(), WithOptional(), v.v. để xác định ánh xạ cho các mối quan hệ mà không phải cả hai đầu đều được hiển thị trong mô hình.

+0

Nhưng nếu tôi tạo cơ sở dữ liệu từ Entity Framework? Bạn chắc chắn tôi sẽ không cần phải phơi bày cả hai tài sản? –

+0

bạn nói đúng, tôi làm bài kiểm tra. cảm ơn bạn, tôi sẽ cập nhật câu hỏi. –

+0

@Acaz: Có lẽ EF sẽ tạo cả hai bộ sưu tập theo mặc định khi bạn tạo mô hình từ DB. Nhưng bạn có thể xóa một bên của mối quan hệ từ các lớp mô hình được tạo ra. – Slauma

1

Tôi tin rằng những gì bạn đang tìm kiếm như sau:

public class Car 
{ 
    public int Id { get; set; } 
    public int ActualPosition { get; private set; } 

    public void Accelerate() 
    { 
     this.ActualPosition += 10; 
    } 
} 

Các đơn vị kiểm tra là dưới đây:

[TestMethod] 
    public void AccellerateWillAddTenUnitsToTheActualPosition() 
    { 
     //Arrange 
     var car = new Car(); 
     var actualPosition = car.ActualPosition; 
     var expectedPosition = actualPosition + 10; 

     //Act 
     car.Accelerate(); 

     //Assert 
     Assert.AreEqual(car.ActualPosition, expectedPosition); 
    } 
Các vấn đề liên quan