2011-09-02 36 views
13

Tôi có một vấn đề trong khi upserting để mongo db bằng cách sử dụng trình điều khiển C# chính thức.Upserting trong Mongo DB và các vấn đề Id

public abstract class AggregateRoot 
{ 
    /// <summary> 
    /// All mongoDb documents must have an id, we specify it here 
    /// </summary> 
    protected AggregateRoot() 
    { 
     Id = ObjectId.GenerateNewId(); 
    } 

    [BsonId] 
    public ObjectId Id { get; set; } 
} 

Thực thể của tôi đã có id nhưng tôi phải tạo Id mongo cụ thể để làm việc, vì tất cả tài liệu trong bộ sưu tập nên có. Bây giờ sau đó tôi nhận được một thực thể mới trong hệ thống của tôi một Id Mongo mới được tạo ra và tôi nhận được mongo không thể thay đổi _id của một tài liệu cũ ngoại lệ. Có một số công việc xung quanh?

Để tôi mô tả thiết kế một chút. Tất cả các thực thể sẽ là được lưu trữ dưới dạng tài liệu được kế thừa từ AggregateRoot có thế hệ id trong đó. Mỗi tài liệu phụ có id của nó được tạo ra tự động và tôi không có vấn đề với điều này. Id trong AggregateRoot được giới thiệu để khắc phục sự cố khi truy xuất dữ liệu từ MongoCollection to List và thế hệ được giới thiệu để id-s khác nhau. Bây giờ chúng ta có thể di chuyển thế hệ id đó để lưu các phương thức vì thực thể mới để cập nhật có một thế hệ id mới. Nhưng nó có nghĩa là mọi dev trong nhóm không được quên tạo id-s trong kho lưu trữ có rủi ro. Nó sẽ đẹp hơn chỉ để bỏ qua id hơn ánh xạ từ Mongo nếu có thể và không có lớp AggregateRoot ở tất cả

+0

Bạn đang lưu các đối tượng của mình như thế nào? Thuộc tính BsonId sẽ buộc MongoDB sử dụng trường đó làm id của bạn. –

+0

Ý tưởng là dữ liệu đến từ một hệ thống bên ngoài để lưu trữ. Nó có id riêng của tôi, tôi phải lưu trữ. Và đây là một id giả vì lợi ích của Mongo. Mỗi tài liệu kế thừa từ AggregateRoot, do đó, điều này được tạo ra khi nhận được mọi đối tượng. Rõ ràng là tôi có thể nhận được cùng một dữ liệu nhưng id mongo được tạo khác nhau. Vì vậy, ngoại lệ xuất hiện –

Trả lời

8

Hình như bạn có thể được thiết lập một cách rõ ràng giá trị Id cho cả chèn và cập nhật. Đó là tốt cho chèn, tất cả các đối tượng mới cần một giá trị _id, tuy nhiên cho các bản cập nhật bạn không được phép thay đổi giá trị của _id trên một tài liệu hiện có sau khi nó được tạo ra.

Cố gắng không đặt giá trị Id chút nào. Nếu bạn không chỉ định giá trị trước khi chèn, trình điều khiển sẽ sử dụng các lớp có sẵn trong IdGenerator để tạo giá trị _id mới, vì vậy nếu đó là một loại ObjectId, nó sẽ sử dụng ObjectIdGenerator. Sau đó, cả chèn và cập nhật của bạn hoạt động tốt.

+0

Nếu tôi xóa thuộc tính id thì thực sự nó không phải là vấn đề khi lưu/cập nhật một thực thể. Vấn đề là nó ném ngoại lệ khi tôi cố gắng tìm kiếm trên bộ sưu tập từ mã vì nó không thể ánh xạ _id đến một thuộc tính sẵn có –

+2

Bạn có thể sử dụng thuộc tính '[BsonIgnoreExtraElements]' trên lớp nếu bộ sưu tập có các trường mà don ' t có tính chất phù hợp. –

50

Tôi đã gặp sự cố tương tự. Tôi muốn nâng cấp tài liệu bằng trình điều khiển C# chính thức. Tôi đã có một lớp như thế này:

public class MyClass 
{ 
    public ObjectId Id { get; set; } 
    public int Field1 { get; set; } 
    public string Field2 { get; set; } 
} 

Trong giao diện điều khiển tôi sẽ viết: db.collection.update({Field1: 3},{Field1: 3, Field2: "value"}) và nó sẽ làm việc. Trong C# tôi đã viết:

collection.Update(Query.EQ("Field1", 3), 
       Update.Replace(new MyClass { Field1 = 3, Field2 = "value" }), 
       UpdateFlags.Upsert); 

và nó không hoạt động! Bởi vì trình điều khiển bao gồm id trống trong câu lệnh cập nhật và khi tôi upsert tài liệu thứ hai với giá trị khác nhau của Field1 ngoại lệ E11000 duplicate key error index được ném (trong trường hợp này Mongo cố gắng chèn tài liệu có _id đã tồn tại trong db).

Khi tôi tự tạo _id (như khởi động chủ đề), tôi đã gặp ngoại lệ tương tự (mongo cannot change _id of a document) về các đối tượng upserting với giá trị hiện tại của Field1.

Giải pháp là để đánh dấu Thuộc tính Id theo thuộc tính [BsonIgnoreIfDefault] (và không khởi tạo nó). Trong trường hợp này, trình điều khiển bỏ qua trường _id trong câu lệnh cập nhật và MongoDb tạo ra Id nếu nó cần thiết.

+8

Bạn cai trị con người, rằng [BsonIgnoreIfDefault] đã tiết kiệm rất nhiều thời gian. Đó là một sự xấu hổ tôi có thể bỏ phiếu nhiều hơn cho bạn. –

+2

Đã lãng phí khoảng một giờ để tìm hiểu lý do tại sao cuộc gọi ReplaceOneAsync của tôi với trình điều khiển 2.0 không hoạt động. Tìm thấy câu trả lời này. Đã thêm [BsonIgnoreIfDefault] và sự cố được giải quyết. Cảm ơn! – BrandonLWhite

+1

Tôi đã dành hàng giờ để tìm ra điều này. CẢM ƠN! – bbrez1

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