2008-11-18 12 views
7

Ok, tôi đã cố gắng chuyển đổi mô hình của mình để sử dụng LINQ nhưng không muốn vứt bỏ DTO hiện tại và các giao diện của chúng. lĩnh vực.Trợ giúp cần thiết cho các hoạt động LINQ to SQL (chèn/cập nhật) với các POCO

Tôi cố gắng tìm bài đăng blog mà đã vạch ra quá trình này khá độc đáo:

Achieving POCOs in LINQ To SQL

Tôi có quản lý để có được việc thu hồi các hồ sơ các đối tượng hoạt động bình thường, tuy nhiên, do tính chất lồng nhau của mô hình của tôi, tôi dường như không thể làm việc bổ sung cho các đối tượng con. Tức là, nếu tôi tạo một đối tượng con, và đặt tham chiếu đến đối tượng cha mẹ mong muốn, LINQ to SQL vẫn ném một ngoại lệ cho biết tham chiếu của đứa trẻ đối với phụ huynh là null. Nếu tôi cố gắng để thêm một đối tượng cha mẹ già đơn giản, nó thành công, nhưng thêm con đối tượng trực tiếp không

Đây là thử nghiệm thất bại của tôi:

[Test] 
    public void AddSelectionShouldAddSelectionToMarket() 
    { 
     Market market = (Market) new Repository().GetMarket(1); 

     Selection selection = new Selection(); 
     selection.Market = market; 

     new Repository().AddSelection(selection); 

     Assert.IsTrue(selection.SID > 0); 
    } 

Dưới đây là thông báo lỗi:

System.InvalidOperationException : Một nỗ lực đã được thực hiện để xóa mối quan hệ giữa Thị trường và Lựa chọn. Tuy nhiên, không thể đặt một trong các khóa ngoại của mối quan hệ (Selection.MID) thành null.

Các bộ phận có liên quan của 2 đối tượng:

[DataContract] 
public class Selection : ISelection 
{ 
    private int mID; 
    [DataMember] 
    public int MID 
    { 
     get { return this.mID; } 
     set { this.mID = value; } 
    } 

    private Market market; 
    [DataMember] 
    public Market Market 
    { 
     get { return this.market; } 
     set 
     { 
      this.market = value; 
      this.mID = value.MID; 
     } 
    } 
} 

[DataContract] 
public class Market : IMarket 
{ 
    private int mID; 
    [DataMember] 
    public int MID 
    { 
     get { return this.mID; } 
     protected set { this.mID = value; } 
    } 

    private List<Selection> selections; 
    [DataMember] 
    public List<Selection> Selections 
    { 
     get { return this.selections; } 
     set 
     { 
      this.selections = value; 
      // For LINQ 
      foreach (Selection selection in selections) 
      { 
       selection.MID = mID; 
       selection.Market = this; 
      } 
     } 
    } 
} 

đang DA của tôi:

 MarketsDataContext context = new MarketsDataContext(); 

     DataLoadOptions options = new DataLoadOptions(); 
     options.LoadWith<Selection>(s => s.Prices); 
     options.LoadWith<Market>(m => m.Selections); 

     context.LoadOptions = options; 
     return context; 

và;

public void AddSelection(ISelection selection) 
    { 
     using (MarketsDataContext context = MarketsDataContext.GetContext()) 
     { 
      context.Selections.InsertOnSubmit((Selection) selection); 
      context.SubmitChanges(); 
     } 
    } 

Và cuối cùng bản đồ XML của tôi:

<Table Name="dbo.Markets" Member="Markets"> 
    <Type Name="Market"> 
     <Column Name="MID" Member="MID" Storage="mID" DbType="Int NOT NULL" IsPrimaryKey="true" IsDbGenerated="true" AutoSync="OnInsert" /> 
     <Association Name="FK_Market-Selections" Member="Selections" Storage="selections" ThisKey="MID" OtherKey="MID" DeleteRule="NO ACTION" /> 
    </Type> 
    </Table> 

    <Table Name="dbo.Selections" Member="Selections"> 
    <Type Name="Selection"> 
     <Column Name="SID" Member="SID" Storage="sID" DbType="Int NOT NULL" IsPrimaryKey="true" IsDbGenerated="true" AutoSync="OnInsert" /> 
     <Column Name="MID" Member="MID" Storage="mID" DbType="Int NOT NULL" /> 
     <Association Name="FK_Market-Selections" Member="Market" Storage="market" ThisKey="MID" OtherKey="MID" IsForeignKey="true" /> 
    </Type> 
    </Table> 

Vì vậy, có thể bất cứ ai chỉ cho tôi đi đúng hướng? Tôi đã tìm kiếm nhiều giờ ...

Edit:

Dưới đây là stacktrace tôi cho thử nghiệm thất bại của tôi:

at System.Data.Linq.ChangeTracker.StandardChangeTracker.StandardTrackedObject.SynchDependentData() 
at System.Data.Linq.ChangeProcessor.ValidateAll(IEnumerable`1 list) 
at System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode) 
at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode) 
at System.Data.Linq.DataContext.SubmitChanges() 
at BetMax.DataModel.Repository.AddSelection(ISelection selection) in Repository.cs: line 68 
at BetMax.DataModel.Test.ModelTest.AddSelectionShouldAddSelectionToMarket() in ModelTest.cs: line 65 

Và phương pháp GetMarket tôi:

public IMarket GetMarket(int MID) 
    { 
     Market market; 
     using (MarketsDataContext context = MarketsDataContext.GetContext()) 
     { 
      market = context.Markets.Single(m => m.MID == MID); 
     } 
     return market; 
    } 

Chỉnh sửa 2:

Vâng, thêm

DeleteOnNull="true" 

để chọn khóa ngoài trong ánh xạ XML đã loại bỏ lỗi khóa ngoài, nhưng bây giờ tôi nhận được tham chiếu null trên một trong các đối tượng con của Selections, nói tham chiếu đến lựa chọn là null mặc dù lựa chọn đang được khởi tạo không có biến nào được đặt (ngoài khóa ngoại). Tôi thậm chí đã cố gắng tạo ra một đối tượng trẻ em, và thiết lập tài liệu tham khảo của nó một cách chính xác nhưng tôi vẫn nhận được lỗi này:

System.NullReferenceException: Object reference not set to an instance of an object. 
at BetMax.DTO.Price.set_Selection(Selection value) in Price.cs: line 25 
at System.Data.Linq.Mapping.PropertyAccessor.Accessor`3.SetValue(ref T instance, V value) 
at System.Data.Linq.Mapping.MetaAccessor`2.SetBoxedValue(ref Object instance, Object value) 
at System.Data.Linq.ChangeProcessor.ClearForeignKeysHelper(MetaAssociation assoc, Object trackedInstance) 
at System.Data.Linq.ChangeProcessor.ClearForeignKeyReferences(TrackedObject to) 
at System.Data.Linq.ChangeProcessor.PostProcessUpdates(List`1 insertedItems, List`1 deletedItems) 
at System.Data.Linq.ChangeProcessor.SubmitChanges(ConflictMode failureMode) 
at System.Data.Linq.DataContext.SubmitChanges(ConflictMode failureMode) 
at System.Data.Linq.DataContext.SubmitChanges() 
at BetMax.DataModel.Repository.AddSelection(ISelection selection) in Repository.cs: line 68 
at BetMax.DataModel.Test.ModelTest.AddSelectionShouldAddSelectionToMarket() in ModelTest.cs: line 69 

Giá là một đối tượng, xây dựng trong cùng mà lựa chọn có liên quan đến thị trường (1 lựa chọn có nhiều mức giá, 1 thị trường có nhiều lựa chọn) v.v.

Trả lời

0

Tôi muốn đề xuất gửi mã của bạn đến Sidar Ok. Anh ấy là một chàng trai tốt và sẽ chỉ cho bạn đi đúng hướng. Hoặc ít nhất đăng một bình luận trên blog của mình chỉ cho anh ta câu hỏi của bạn ở đây.

4

Tôi đoán vấn đề nằm trong phương pháp thử nghiệm của bạn. Bạn đã tạo một Kho lưu trữ với một DataContext nhưng bạn đã gửi các bản đệ trình của bạn với một tệp khác.

[Test] 
public void AddSelectionShouldAddSelectionToMarket() 
{ 
    Market market = (Market) new Repository().GetMarket(1); 

    Selection selection = new Selection(); 
    selection.Market = market; 

    new Repository().AddSelection(selection); 

    Assert.IsTrue(selection.SID > 0); 
} 

Tạo một Kho lưu trữ và sử dụng nó trong phương pháp thử nghiệm.

[Test] 
public void AddSelectionShouldAddSelectionToMarket() 
{ 
    Repository repository = new Repository(); 
    Market market = (Market) repository.GetMarket(1); 

    Selection selection = new Selection(); 
    selection.Market = market; 

    repository.AddSelection(selection); 

    Assert.IsTrue(selection.SID > 0); 
} 
+0

Ahh rất tốt điểm. Tôi sẽ thực sự xử lý bối cảnh mỗi khi tôi làm một hoạt động, vì vậy tôi sẽ xem nếu kiên trì nó lâu hơn một chút sẽ giúp ... – mwjackson

+0

Vâng có vẻ như điều này đã không giải quyết được vấn đề. – mwjackson

2

Chỉ cần một đoán nhưng nó có thể có mặt ở đây

public Market Market 
{ 
    get { return this.market; } 
    set 
    { 
     this.market = value; 
     this.mID = value.MID; 
    } 
} 

gì xảy ra khi giá trị mà bạn thiết lập để thị trường là null? Dòng cuối cùng sẽ không hợp lệ vì nó không thể giải quyết null.MID. Có lẽ bạn cần điều này cho setter của bạn:

set 
    { 
     this.market = value; 
     this.mID = (value == null) ? null : value.MID; 
    } 

Cũng MID của bạn sẽ được nullable

int? MID 
+0

Không, nó không phải là một vấn đề (tôi nghĩ). Đây chính là cách tiếp cận mà SidarOK đang thực hiện trong bài đăng trên blog ... – mwjackson

+0

Nhưng khi GeekyMonkey đề cập đến điều khiển này sẽ làm cho lớp của bạn ổn định hơn. Bởi vì thuộc tính Market của bạn được mở để thiết lập null, vì vậy hãy kiểm tra xem nó có phải là null không sẽ không thành vấn đề. –

+0

Nhưng treo trên, tôi muốn đảm bảo rằng các lĩnh vực quan trọng nước ngoài (ví dụ như MID trong lựa chọn) không phải là null ... Cho phép null có thể dẫn đến các mục mồ côi trong DB. – mwjackson

2

Đối với vấn đề mới của bạn; Vấn đề xảy ra khi gán null cho thuộc tính lựa chọn của Price. Bạn đã làm điều đó bằng mã của bạn? Bạn có thể một lần nữa cho phần mã mà bạn có ngoại lệ? Ý tôi là chuyển nhượng sang thực thể Giá ...

Chỉnh sửa theo nhận xét: Tôi đoán đó là do ngoại lệ kiểm soát null như chúng tôi đã đề cập trước đó trên bài đăng GeekyMonkeys. Trong việc khởi tạo lớp lựa chọn, thuộc tính Price cần thiết lập là null nhưng khi null được gán cho nó, nó ném tham chiếu null. Vì vậy, bạn phải làm một điều khiển null trong bộ tài sản giá.

private List<Price> prices 
[DataMember] 
public List<Price> Prices 
{ 
    get { return this.prices; } 
    set 
    { 
     if(value != null) 
     { 
      this.pricess = value; 
      // For LINQ    
      foreach (Price price in prices) 
      { 
      price.MID = mID; 
      price.Selection = this; 
      } 
     } 
    } 
} 
+0

Tôi hiện không chạm vào Giá. Tất cả những gì tôi đang cố gắng thực hiện tại thời điểm này là thực hiện kiểm tra ở trên để tạo ra một Lựa chọn mới (với Danh sách rỗng ) và thêm nó vào đối tượng Market. Bằng cách nào đó cấu hình của tôi là ném một lỗi ref null từ Giá? – mwjackson

+0

Tôi chỉnh sửa bài đăng của mình, xem nó. –

+0

Ok tôi sẽ cung cấp cho nó một đi và cho bạn biết làm thế nào tôi nhận được trên. Cảm ơn một lần nữa! – mwjackson

2

Tôi biết nó được một lúc và bạn đã có thể đã giải quyết vấn đề này, nhưng có lẽ không ...

Tôi giả định rằng cấu trúc dữ liệu của bạn là tương tự như sau:

Market 
====== 
Market_ID  int not null identity (1, 1) 


Selection 
========= 
Selection_ID int not null identity (1, 1) 
Market_ID  int (FK to Market) 
Selection_Name varchar(50) 

để thêm một thị trường mới và một lựa chọn mới cùng một lúc:

Selection selection = new Selection(); 
Market market = new Market(); 

market.Selections.Add(selection); 
DataContext.Markets.InsertOnSubmit(market); 
DataContext.SubmitChanges(); 

để thêm một lựa chọn mới cho một exis Thị trường ting:

Selection selection = new Selection(); 
Market market = DataContext.Markets.Where(a => a.Market_ID == 7).Single(); 

market.Selections.Add(selection); 
DataContext.SubmitChanges(); 

Để cập nhật Lựa chọn đầu tiên trong một thị trường:

Selection selection = DataContext.Markets.Where(a => a.Market_ID == 7).Selections.First(); 

selection.Selection_Name = "New Name"; 
DataContext.SubmitChanges();