2012-08-16 33 views
14

Tôi có một bảng Child Chánh đơn giản trong một cơ sở dữ liệu như vậyTại sao linq-2-sql lại tạo thêm các đối tượng không cần thiết?

CREATE TABLE [Parent](
    [Id] [int] IDENTITY(1,1) NOT NULL, 
    [Name] [nvarchar](256) NOT NULL)  
ALTER TABLE [Parent] ADD CONSTRAINT [PK_Parent_Id] PRIMARY KEY ([Id])  

CREATE TABLE [Child](
    [Id] [int] IDENTITY(1,1) NOT NULL, 
    [ParentId] [int] NOT NULL, 
    [Name] [nvarchar](256) NOT NULL)  
ALTER TABLE [Child] ADD CONSTRAINT [PK_Child_Id] PRIMARY KEY ([Id]) 
ALTER TABLE [Child] ADD CONSTRAINT [FK_Child_Parent_ID] 
    FOREIGN KEY([ParentId]) REFERENCES [Parent] ([Id]) 

Các dữ liệu mà tôi có trong họ được

Bảng Chánh

Id Name 
1 John 

Bảng Child

Id ParentId Name 
1  1 Mike 
2  1 Jake 
3  1 Sue 
4  1 Liz 

Những bảng này được ánh xạ tới ParentChild đối tượng C# sử dụng trình thiết kế LINQ-2-SQL trong Visual Studio mà không có tùy chọn không chuẩn.

tôi đã thực hiện một chương trình thử nghiệm đơn giản để truy vấn tất cả con với cha mẹ

public partial class Parent 
{ 
    static int counter = 0; 
    //default OnCreated created by the linq to sql designer 
    partial void OnCreated() 
    { 
     Console.WriteLine(string.Format("CreatedParent {0} hashcode={1}", 
      ++counter , GetHashCode())); 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     using (var db = new SimpleDbDataContext()) 
     { 
      DataLoadOptions opts = new DataLoadOptions(); 
      opts.LoadWith<Child>(c => c.Parent); 
      db.LoadOptions = opts; 
      var allChildren = db.Childs.ToArray(); 
      foreach (var child in allChildren) 
      { 
       Console.WriteLine(string.Format("Parent name={0} hashcode={1}", 
        child.Parent.Name, child.Parent.GetHashCode())); 

      } 
     } 
    } 
} 

Đầu ra của chương trình trên là

CreatedParent 1 hashcode=53937671 
CreatedParent 2 hashcode=9874138 
CreatedParent 3 hashcode=2186493 
CreatedParent 4 hashcode=22537358 
Parent name=John hashcode=53937671 
Parent name=John hashcode=53937671 
Parent name=John hashcode=53937671 
Parent name=John hashcode=53937671 

Như bạn có thể thấy một đối tượng Parent đã được tạo ra cho mỗi Child trong cơ sở dữ liệu chỉ để được loại bỏ cuối cùng.

Câu hỏi:

  1. Tại sao LINQ-2-Sql tạo ra những không cần thiết thêm Parent đối tượng?
  2. Có bất kỳ tùy chọn nào để tránh tạo thêm Parent đối tượng không?
+0

Nó không tạo ra các đối tượng đơn lẻ như bạn đang mong đợi và cũng không nên. Điều gì sẽ xảy ra nếu bạn có một truy vấn đã chọn một đối tượng và bạn bắt đầu viết một truy vấn cập nhật trên cùng một id? Bạn có thấy ngay kết quả của thay đổi trước khi gửi các thay đổi không? Một cá thể duy nhất được tạo cho mỗi truy vấn. –

+0

@JeffMercado, không: L2S chỉ đưa ra một ví dụ cho mỗi bảng và khóa. Đây là một tính năng quan trọng của ORM (bản đồ nhận dạng). – usr

Trả lời

12

Đây là tác dụng phụ của cách thức, LoadWith được triển khai. LINQ to SQL chuyển đổi truy vấn của bạn thành nội bộ:

from c in children 
select { Child = c, Parent = c.Parent } 

Như bạn có thể thấy, chúng tôi đang tải phụ huynh một lần cho mọi trẻ em (tham gia bên trong). Hiệu ứng này thường không nhìn thấy được vì bản đồ nhận dạng. ORM đảm bảo rằng các đối tượng thực thể không bao giờ bị trùng lặp bởi (bảng, khóa chính). Điều này có ích khi bạn cập nhật.

LINQ to SQL đọc tập kết quả được trả về từ máy chủ (nó chứa cùng thời gian N của phụ huynh!) Và mô tả nó thành các đối tượng. Chỉ sau khi materialization được thực hiện, bản đồ nhận dạng thực hiện công việc của mình và loại bỏ các bản sao cha mẹ trùng lặp.

Hiệu ứng tương tự hoạt động cho tất cả các truy vấn trả về cùng một thực thể nhiều lần.

+3

Chính xác nó là một tham gia bên trong. Nó giống như viết truy vấn này và chạy trong SSMS. SELECT * FROM child THAM GIA cha mẹ trên child.ParentId = Parent.Id ... khi bạn chạy truy vấn này bạn nhận được id cha cho mỗi đứa trẻ không có gì mới, trên thực tế ở đây VS đang theo bước chuẩn của chuẩn SQL. – MStp

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