2015-10-22 6 views
0

Использования Microsoft SQL-сервер принимает следующий образец таблицу с рекуррентным соотношениемВставка рекурсивный/вложенный объект в рекурсивной таблице

[dbo].[IPAddress] 
(
    [IPAddressID] [int] PRIMARY KEY IDENTITY(1,1), 
    [IP] [nchar] (15), 
    [ParentID] [int] FOREIGN KEY REFERENCES [IPAddressID] 
) 

Я следующий вложенный объектом, который содержит список одного типа объектов

public class IPAddress 
{ 
    public int IPAddressID { get; set; } 
    public string IP { get; set; } 
    public IPAddress[] Childs { get; set; } 
} 

var IP = new IPAddress 
{ 
    IP = "10.0.0.0", 
    Childs = new IPAddress[] 
    { 
     new IPAddress 
     { 
      IP="10.1.0.0", 
      Childs = new IPAddress[] 
      { 
       new IPAddress{ IP="10.1.1.0" }, 
       new IPAddress{ IP="10.1.2.0" }, 
       new IPAddress{ IP="10.1.3.0" } 
      } 
     } 
    } 
}; 

Когда вставка, что объект, данные в таблице должны быть такими:

IPAddressID,IP,ParentID 
10,'10.0.0.0',Null 
12,'10.1.0.0',10 
13,'10.1.1.0',12 
14,'10.1.2.0',12 
15,'10.1.3.0',12 

В моей реальной с ase базовый объект может иметь 60 дочерних элементов второго уровня, каждый ребенок второго уровня имеет 4 ребенка на третьем уровне, тогда число плоских объектов равно 1 + 60 + (60 * 4) = 2461 объект/строка, а объект имеет 25 свойство, сопоставленное с 25 столбцами в иерархии таблиц наследования, так что лучший способ вставить этот объект в таблицу с помощью C# ado.net? могу ли я использовать cte в этом?

ответ

1

Вот один из способов сделать это. Вы можете попробовать вызвать этот метод, передав свой объект IPAddress. Вы можете создать строку вставки со всеми запросами и вызвать ExecuteNonQuery только один раз, если хотите быть более эффективными. Будьте осторожны: в каждом запросе задано ограничение на 1000 вложений.

public void InsertIpAdress(IPAddress myipaddress) 
{ 
string cs = "Put your connection string" 
SqlConnection cn = new SqlConnection(cs); 

try 
{ 
    //Open connection 
    cn.Open(); 

    //First we insert the parent(Use stored procedure provided if you want) 
    SqlCommand cm = new SqlCommand("[dbo].[AddParent]", cn); 
    cm.CommandType = CommandType.StoredProcedure; 

    //Add parameter 
    cm.Parameters.AddWithValue("@IP", myipaddress.IP); 

    //Output parameter 
    SqlParameter output = new SqlParameter("@Parent",SqlDbType.Int); 
    output.Direction = ParameterDirection.Output; 
    cm.Parameters.Add(output); 

    //Execute query 
    cm.ExecuteNonQuery(); 

    //Here we get parent id 
    int parent = Convert.ToInt32(output.Value.ToString()); 

    //Then we have to add every children 
    cm = new SqlCommand("INSERT INTO YourTable (IP,ParentID) VALUES (@ip,@parent);", cn); 

    //Add parent as parameter 
    cm.Parameters.AddWithValue("@parent", parent); 

    foreach(IPAddress element in myipaddress.Childs) 
    { 
     //Add the current child ip 
     cm.Parameters.AddWithValue("@ip", element.IP); 

     //Execute command 
     cm.ExecuteNonQuery(); 
    } 
    //Close connection 
    cn.Close(); 
} 
catch(Exception ex) 
{ 
    //You can handle exceptions here 
    MessageBox.Show(ex.message); 
} 
} 

И вот что хранимая процедура будет выглядеть

ALTER PROCEDURE [dbo].[AddParent] 
    @IP   NVARCHAR(50), 
    @Parent  INT OUTPUT 
AS 
BEGIN 
    SET NOCOUNT ON; 

    INSERT INTO YourTable (IP,ParentID) VALUES (IP,null); 
    SET @Parent = SCOPE_IDENTITY(); 
END;