2013-05-15 31 views
10

Sau khi tôi đọc một câu hỏi trong liên kết đính kèm, tôi đã biết cách đặt cột DateCreated và DateModified trong Entity Framework và sử dụng nó trong ứng dụng của tôi. Tuy nhiên, theo cách thức SQL cũ, cách kích hoạt phổ biến hơn vì nó an toàn hơn từ quan điểm của DBA.Cột DateCreated hoặc Modified - Entity Framework hoặc sử dụng trình kích hoạt trên SQL Server

Vì vậy, bất kỳ lời khuyên nào về cách nào là phương pháp hay nhất? nên được đặt trong khung thực thể cho mục đích toàn vẹn ứng dụng? hoặc nên sử dụng trình kích hoạt vì nó có ý nghĩa hơn từ quan điểm bảo mật dữ liệu? Hoặc là có một cách để soạn kích hoạt trong khuôn khổ thực thể? Cảm ơn.

EF CodeFirst: Rails-style created and modified columns

BTW, mặc dù nó không quan trọng nhiều, tôi đang xây dựng ứng dụng này sử dụng ASP.NET MVC C#.

Trả lời

20

Ý kiến: Kích hoạt giống như hành vi ẩn, trừ khi bạn tìm kiếm chúng thường không nhận ra chúng ở đó. Tôi cũng muốn giữ cho DB càng “câm” càng tốt khi sử dụng EF, vì tôi đang sử dụng EF nên nhóm của tôi sẽ không cần phải duy trì mã SQL.

Đối với giải pháp của tôi (kết hợp của ASP.NET WebForms và MVC trong C# với Logic kinh doanh trong một dự án mà còn chứa các DataContext):

tôi thời gian gần đây đã có một vấn đề tương tự, và mặc dù cho hoàn cảnh của tôi nó phức tạp hơn (DatabaseFirst, vì vậy yêu cầu tệp TT tùy chỉnh), giải pháp hầu như giống nhau.

Tôi tạo ra một giao diện:

public interface ITrackableEntity 
{ 
    DateTime CreatedDateTime { get; set; } 
    int CreatedUserID { get; set; } 
    DateTime ModifiedDateTime { get; set; } 
    int ModifiedUserID { get; set; } 
} 

Sau đó, tôi chỉ thực hiện mà giao diện trên bất kỳ đơn vị tôi cần phải (vì giải pháp của tôi là DatabaseFirst, tôi cập nhật các tập tin TT để kiểm tra xem bàn có bốn cột, và nếu có thêm giao diện vào đầu ra).

CẬP NHẬT: đây là sự thay đổi của tôi để các tập tin TT, nơi tôi cập nhật các EntityClassOpening() phương pháp:

public string EntityClassOpening(EntityType entity) 
{ 
    var trackableEntityPropNames = new string[] { "CreatedUserID", "CreatedDateTime", "ModifiedUserID", "ModifiedDateTime" }; 
    var propNames = entity.Properties.Select(p => p.Name); 
    var isTrackable = trackableEntityPropNames.All(s => propNames.Contains(s)); 
    var inherits = new List<string>(); 
    if (!String.IsNullOrEmpty(_typeMapper.GetTypeName(entity.BaseType))) 
    { 
     inherits.Add(_typeMapper.GetTypeName(entity.BaseType)); 
    } 
    if (isTrackable) 
    { 
     inherits.Add("ITrackableEntity"); 
    } 

    return string.Format(
     CultureInfo.InvariantCulture, 
     "{0} {1}partial class {2}{3}", 
     Accessibility.ForType(entity), 
     _code.SpaceAfter(_code.AbstractOption(entity)), 
     _code.Escape(entity), 
     _code.StringBefore(" : ", String.Join(", ", inherits))); 
} 

Điều duy nhất còn lại là thêm dòng sau vào lớp DataContext một phần của tôi:

public override int SaveChanges() 
    { 
     // fix trackable entities 
     var trackables = ChangeTracker.Entries<ITrackableEntity>(); 

     if (trackables != null) 
     { 
      // added 
      foreach (var item in trackables.Where(t => t.State == EntityState.Added)) 
      { 
       item.Entity.CreatedDateTime = System.DateTime.Now; 
       item.Entity.CreatedUserID = _userID; 
       item.Entity.ModifiedDateTime = System.DateTime.Now; 
       item.Entity.ModifiedUserID = _userID; 
      } 
      // modified 
      foreach (var item in trackables.Where(t => t.State == EntityState.Modified)) 
      { 
       item.Entity.ModifiedDateTime = System.DateTime.Now; 
       item.Entity.ModifiedUserID = _userID; 
      } 
     } 

     return base.SaveChanges(); 
    } 

Lưu ý rằng tôi đã lưu ID người dùng hiện tại trong một trường riêng tư trên lớp DataContext mỗi khi tôi tạo nó.

+0

đây là một câu trả lời chi tiết, Cảm ơn bạn Tim. Tôi bị tổn thương theo cách của bạn và nó là tốt để duy trì logic này trong lớp ứng dụng. Bạn có nghĩ nhóm EF có thể bổ sung các ràng buộc mặc định và kích hoạt hỗ trợ vào DataAnnotation hoặc FluentAPI không? – anIBMer

+1

Tôi sẽ chào đón đội EF thêm vào đó, nó sẽ làm mọi việc dễ dàng hơn cho các quy tắc đơn giản. Điều đó nói rằng, có rất thường xuyên ngoại lệ cho các quy tắc, vì vậy biết làm thế nào để kiểm soát hoàn toàn của quá trình này là một kỹ năng có giá trị để tìm hiểu. –

+0

Chính xác bạn đã thực hiện những cập nhật nào đối với tệp TT? – Fergal

6

Đối với DateCreated, tôi chỉ thêm ràng buộc mặc định trên cột đó được đặt là SYSDATETIME() có hiệu lực khi chèn hàng mới vào bảng.

Đối với DateModified, cá nhân, tôi có thể sử dụng trình kích hoạt trên các bảng đó.

Theo tôi, cách tiếp cận kích hoạt:

  • làm cho nó dễ dàng hơn; Tôi không phải lo lắng và nhớ mỗi khi tôi lưu một thực thể để thiết lập rằng DateModified

  • làm cho nó "an toàn hơn" ở chỗ nó cũng sẽ áp dụng DateModified nếu ai đó tìm cách để sửa đổi dữ liệu trong ứng dụng của tôi cơ sở dữ liệu trực tiếp (sử dụng ví dụ như Access hoặc Excel hoặc một cái gì đó).

+0

Tôi đang sử dụng mã đầu tiên, do đó, trình kích hoạt có thể được tạo trong DB-Migration. Mặc dù để thêm một ràng buộc mặc định vào một cột, tôi không nghĩ rằng tôi có thể làm điều đó thông qua DBMigration hoặc chú thích dữ liệu, tôi có thể? – anIBMer

2

Tôi đồng ý với marc_s - an toàn hơn nhiều để kích hoạt (s) trong cơ sở dữ liệu. Trong cơ sở dữ liệu của công ty tôi, tôi yêu cầu mỗi trường có một trường Date_Modified, Date_Created và thậm chí tôi còn có chức năng tiện ích để tự động tạo các trình kích hoạt cần thiết.

Khi sử dụng với Entity Framework, tôi thấy mình cần phải sử dụng các chú thích [DatabaseGenerated] với các lớp POCO tôi:

[Column(TypeName = "datetime2")] 
[DatabaseGenerated(DatabaseGeneratedOption.Computed)] 
public DateTime? Date_Modified { get; set; } 

[Column(TypeName = "datetime2")] 
[DatabaseGenerated(DatabaseGeneratedOption.Computed)] 
public DateTime? Date_Created { get; set; } 

Tôi đã cố gắng sử dụng bản đồ thủ tục được lưu trữ trên một thực thể, và EF được tạo @Date_Modified , @Date_Created thông số trên chèn/cập nhật sprocs của tôi nhận được lỗi

Quy trình hoặc chức năng có quá nhiều đối số được chỉ định.

Hầu hết các ví dụ hiển thị sử dụng [NotMapped], cho phép chọn/chèn để hoạt động nhưng sau đó các trường đó sẽ không hiển thị khi thực thể đó được tải!

Cách khác bạn có thể đảm bảo rằng mọi sprocs chứa thông số @Date_Modified, @Date_Created, nhưng điều này ngược lại với thiết kế sử dụng trình kích hoạt ở vị trí đầu tiên.

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