2013-10-25 48 views
1

我正在研究一個Windows應用程序,它針對.net 4,從多個平臺獲取訂單信息。我需要將數據存儲在本地數據庫中,並決定使用LINQ to SQL,此刻,我的Order類有相當數量的代碼來處理髮送給每個平臺的數據,所以我一直使用裝飾器來添加屬性而不是在Visual Studio中使用設計器。指定的演員表與EntitySet之間使用一對多關係無效

它似乎是主要工作,但是當查詢一個訂單數據庫它只能成功返回主要訂單數據,並試圖枚舉項目實體集它拋出一個「指定的轉換無效」。例外。程序會正確地將訂單插入到訂單表格和訂單行/項目到OrdersLines表格中,它還將讀取OrdersLines表格並正確返回填充的OrderLine對象。

Database layout我有OrdersLines掛Orders.orderID

類的外鍵約束:

[Table(Name = "Orders")] 
public class Order 
{ 
    [Column(Name="orderID",IsPrimaryKey=true, IsDbGenerated=false)] 
    public string OrderID; 
    [Column(Name = "sourceID")] 
    public int SourceID; 
    [Column(Name = "statusID")] 
    public int StatusID = 1; 
    [Column(Name = "externalOrderID")] 
    public string ExternalOrderID; 
    [Column(Name = "deliveryName")] 
    public string Recipient = ""; 
    [Column(Name = "deliveryCompany")] 
    public string Company = ""; 
    [Column(Name = "deliveryAddress1")] 
    public string Address1 = ""; 
    [Column(Name = "deliveryAddress2")] 
    public string Address2 = ""; 
    [Column(Name = "deliveryAddress3")] 
    public string Address3 = ""; 
    [Column(Name = "deliveryTown")] 
    public string Town = ""; 
    [Column(Name = "deliveryCounty")] 
    public string County = ""; 
    [Column(Name = "deliveryCountry")] 
    public string Country = ""; 
    [Column(Name = "deliveryCountryISO")] 
    public string CountryISO = ""; 
    public Country RMCountryData; 
    [Column(Name = "deliveryPostcode")] 
    public string Postcode = ""; 
    public Int64 TotalWeight = 0; 
    public ShippingType ShippingType = ShippingType.Standard; 
    public ShippingDestination ShippingDestination = ShippingDestination.International; 
    [Column(Name = "email")] 
    public string Email = ""; 

    private EntitySet<OrderLine> _Items = new EntitySet<OrderLine>(); 
    [Association(Name = "FK_OrdersLines_Orders", Storage = "_Items")] 
    public EntitySet<OrderLine> Items 
    { 
     set 
     { 
      this._Items.Assign(value); 
     } 
     get 
     { 
      return this._Items; 
     } 
    } 

    public Order() { } 

    public void Save() 
    { 
     OrderDataContext context = new OrderDataContext(String.Format(Settings.Default.ConnectionString, Settings.Default.DBUser, Settings.Default.DBPassword, Settings.Default.DBServer, Settings.Default.DBName)); 
     context.Log = Console.Out; 
     var query = from o in context.Order where o.OrderID.Equals(this.OrderID) select o; 
     var line = from l in context.OrderLine where l.OrderID.Equals(this.OrderID) select l; 

     if (query.Count() == 0) 
     { 
      context.Order.InsertOnSubmit(this); 
      context.SubmitChanges(); 
     } 
     else 
     { 
      foreach (var customerOrder in query) 
      { 
       Console.WriteLine(customerOrder.OrderID); 
       foreach (var orderItem in customerOrder.Items) 
       { 
        Console.WriteLine(orderItem.Name); 
       } 
      } 
     } 
    } 
} 

[Table(Name = "OrdersLines")] 
public class OrderLine 
{ 
    [Column(Name = "localLineID", IsPrimaryKey = true, IsDbGenerated = true)] 
    public int LocalLineID; 
    [Column(Name = "orderID")] 
    public string OrderID; 
    [Column(Name = "lineID")] 
    public Int64 LineID; 
    public Int64 ProductID; 
    [Column(Name = "sku")] 
    public Int64 SKU; 
    [Column(Name = "name")] 
    public string Name; 
    [Column(Name = "quantity")] 
    public int Quantity; 
    [Column(Name = "weight")] 
    public Int64 Weight; 

    public OrderLine() { } 

    public OrderLine(Order Parent, Int64 SKU, Int64 LineID, string Name, int Quantity) 
    { 
     this.OrderID = Parent.OrderID; 
     this.LineID = LineID; 
     this.ProductID = 0; 
     this.SKU = SKU; 
     this.Name = Name; 
     this.Quantity = Quantity; 
     this.Weight = 0; 
    } 
} 

public partial class OrderDataContext : DataContext 
{ 
    public Table<Order> Order; 
    public Table<OrderLine> OrderLine; 

    public OrderDataContext(String connString) : base(connString) { } 
} 

的異常就行拋出 「的foreach(在customerOrder.Items VAR OrderItem的)」

堆棧跟蹤:

at System.Data.Linq.IdentityManager.StandardIdentityManager.SingleKeyManager`2.TryCreateKeyFromValues(Object[] values, V& v) 
at System.Data.Linq.IdentityManager.StandardIdentityManager.IdentityCache`2.Find(Object[] keyValues) 
at System.Data.Linq.CommonDataServices.DeferredSourceFactory`1.TryGetCachedObject(Object[] keyValues, T& cached) 
at System.Data.Linq.CommonDataServices.DeferredSourceFactory`1.Execute(Object instance) 
at System.Data.Linq.EntitySet`1.Load() 
at System.Data.Linq.EntitySet`1.GetEnumerator() 
at System.Linq.SystemCore_EnumerableDebugView`1.get_Items() 
+0

歡迎堆棧溢出!不幸的是,我在解決你的問題時遇到了一些麻煩。你可以發佈調用Linq To SQL的代碼嗎? – Aron

+0

是的,抱歉,如果我沒有說清楚,它的內部foreach循環在Order.Save()拋出異常。如果我在2 LINQ查詢之後中斷並檢查結果,則查詢將包含正確填充的Order對象,除非在展開引發異常時_Items將無法枚舉,則OrdersLine查詢將返回該訂單的所有訂單行的完整列表OrderLine對象正確填充。請致電 – Technofrood

+0

。 :) – Aron

回答

0

根據我在數據庫佈局中看到的內容(SQL Server Management Studio的屏幕截圖?),「weight」和「lineID」列被定義爲「Allow Nulls」。

但進入您發佈的OrderLine類定義,LineIDWeight屬性不Nullable

[Table(Name = "OrdersLines")] 
public class OrderLine 
{ 
    // ... 
    [Column(Name = "lineID")] 
    public Int64 LineID; 
    // ... 
    [Column(Name = "weight")] 
    public Int64 Weight; 

LINQ2SQL肯定是希望這些屬性爲Nullable,它可以解釋爲什麼你會得到一個Specified cast is not valid:分配可能因爲列數據庫類型不匹配C#屬性類型而失敗。

嘗試,而不是使用此代碼:

[Table(Name = "OrdersLines")] 
public class OrderLine 
{ 
    // ... 
    [Column(Name = "lineID")] 
    public Int64? LineID; 
    // ... 
    [Column(Name = "weight")] 
    public Int64? Weight; 

編輯

我還注意到,orderIdnvarchar(30)localLineIdint。在生成連接SQL語句時,這可能會成爲Linq2SQL的一個問題,並且確實值得嘗試將它們設置爲相同類型。

最後和這就是問題所在:

[Association(Name = "FK_OrdersLines_Orders", Storage = "_Items")] 

應該是這樣的:

[Association(Name = "FK_OrdersLines_Orders", Storage = "_Items", OtherKey = "OrderID")] 
+0

嗨,我暫時改變了那些列不允許空值,但我仍然得到相同的錯誤。 LINQ似乎工作正常,如果我單獨查詢每個表,它只是無法將OrderLines加載到Order._Items。例如'var line = from l in context.OrderLine where l.OrderID.Equals(this.OrderID)select l;''將產生一個OrderLines集合,然後我可以迭代。 – Technofrood

+0

另一個問題是,您的OrderDataContext構造函數或別處的屬性DeferredLoadingEnabled設置爲false? – AirL

+0

我沒有明確地將它設置爲任何內容,因此它應該使用DataContext的默認值,如果在初始化後斷開,它將DeferredLoadingEnabled設置爲true。 – Technofrood