2013-10-08 141 views
1

我正在尋找如何在運行時通過字符串變量在表中選擇LINQ的方法。實體框架按名稱獲取表

這是我到目前爲止使用反射:

private Entities ctx = new Entities(); 

public List<AtsPlatform> GetAtsPlatformByName(string atsPlatformName) 
{ 

    List<AtsPlatform> atsPlatform = null; 
    System.Reflection.PropertyInfo propertyInfo = ctx.GetType().GetProperty(atsPlatformName.ToLower()); 
    var platform = propertyInfo.GetValue(ctx, null); 

    // it fails here highlighting "platform" with error that reads "Error 1 Could not find an implementation of the query pattern for source type 'System.Data.Objects.ObjectQuery'. 'Select' not found. Consider explicitly specifying the type of the range variable 'ats'." 
    atsPlatform = ((from ats in platform select new AtsPlatform { RequestNumber = ats.RequestNumber, NumberOfFail = ats.NumberOfFail, NumberOfFailWithCR = ats.NumberOfFailWithCR, NumberOfTestCase = ats.NumberOfTestCase }).ToList());   

    return atsPlatform; 
} 

在我的模型類,我:

public class AtsPlatform 
{ 
public string Name { get; set; } 
public string RequestNumber { get; set; } 
public Int32? NumberOfFail { get; set; } 
public Int32? NumberOfTestCase { get; set; } 
public Int32? NumberOfFailWithCR { get; set; } 
} 

在數據庫,我有以下表格: 「ATS1」,「 ats2「,」ats3「..」atsN「,其中每個都與」AtsPlatform「中定義的屬性具有相同的實體字段。

我想要做的只是:

List<AtsPlatform> a1 = GetAtsPlatformByName("ats1"); 
List<AtsPlatform> a2 = GetAtsPlatformByName("ats2"); 
List<AtsPlatform> aN = GetAtsPlatformByName("atsN"); 

我可以使用「開關」,但這使代碼更少展開,並且需要更新,無論何時創建新的「ats(N + 1)」。

我2天的研究導致我無處可去,但回到了零。我很困難。

請幫助!謝謝!

+0

你是否爲每個表創建了實體?在實體類「ats1」和「ats2」上實際上有一個屬性嗎? –

+0

正確。 「ats1」,「ats2」...「atsN」已經可供使用。 – user3758380

+0

什麼是房產類型? –

回答

1

而不是反射,如何使用SqlQuery函數?

所以

List<AtsPlatform> GetAtsPlatformByName(int index) 
{ 
    using (var ctx = new Entities()) 
    { 
     return ctx.Database.SqlQuery<AtsPlatform>("SELECT * FROM dbo.ats" + index) 
          .ToList(); 
    } 
} 

而且,沒有變化上使用數據庫對象的SqlQuery類方法(這是確定你的情況,我想,因爲AtsPlatform類只包含基本屬性)的實體進行跟蹤。

對於變化的跟蹤,你將需要使用DbSet SqlQuery類方法,並可能需要把一些反思。

+0

嗨Umair, 我無法在intellisense中找到「ctx.Database」,可能是因爲我正在使用MySQL DB。我發現使用「ctx.ExecuteStoreCommand」的在線類似示例,但即使使用簡單查詢也無法正常工作。任何建議? – user3758380

+0

奇怪。看起來好像你使用的是數據庫優先?上下文中的ExecuteStoreQuery方法如何? – Umair

+0

是的,我做數據庫優先,因爲我不是數據庫的所有者。我做了一些關於ExecuteStoreQuery的研究,它似乎工作。 以下是摘錄: List atsPlatforms = null; string stm = String.Format("SELECT RequestNumber, NumberOfFail, NumberOfTestCase, NumberOfFailWithCR FROM {0}", atsPlatformName); atsPlatforms = new List(); foreach (AtsPlatform ats in ctx.ExecuteStoreQuery(stm)) { atsPlatforms.Add(ats); } user3758380

0

我不知道你在做什麼工作這樣。你應該創建一個基於單個「主」表的實體,例如。 Ats

完成此操作後,您的Entities類中將有一個屬性,名稱爲Ats。現在可以使用此屬性來選擇使用這種原始SQL查詢的實體。

var atsName = "ats1"; 

using (var context = new Entities()) 
{ 
    var blogs = context.Ats.SqlQuery(string.Format("SELECT * FROM {0}", atsName)).ToList(); 
} 

您也可以試試這個(我假設的屬性類型是DBSet因爲你沒有在一個問題中指定它)

var platform = propertyInfo.GetValue(ctx, null) as DBSet<Ats>; 

atsPlatform = platform.Select(ats => new A new AtsPlatform { RequestNumber = ats.RequestNumber, NumberOfFail = ats.NumberOfFail, NumberOfFailWithCR = ats.NumberOfFailWithCR, NumberOfTestCase = ats.NumberOfTestCase }).ToList();  

return atsPlatform; 
1

對不起,我的反應遲緩,因爲我不知道過嘗試不同的解決方案:

溶液#1:主表

如@Alexw建議的,建立一個主表如果允許更改數據庫的設計,則工作得最好。我目前正在與數據庫所有者合作進行此更改。由於依賴關係,這種改變必須等到下一階段。

同時,我創建了模擬db來實踐這種方法。

解決方案2:原始查詢

的建議通過@Umair,原始查詢將做的工作。我創建了一個處理原始sql查詢的類。

public class AtsRawQuery 
{ 
    private string ConnetionString = ""; 

    public AtsRawQuery(string connectionString) 
    { 
     this.ConnetionString = connectionString; 
    } 

    public List<List<string>> Query(string queryString) 
    { 
     List<List<string>> results = null; 
     MySqlConnection conn = null; 
     MySqlDataReader rdr = null; 

     try 
     { 
      conn = new MySqlConnection(this.ConnetionString); 
      conn.Open(); 

      MySqlCommand cmd = new MySqlCommand(queryString, conn); 
      rdr = cmd.ExecuteReader(); 

      if (rdr.HasRows) 
      { 
       results = new List<List<string>>(); 
       while (rdr.Read()) 
       { 
        List<string> curr_result = new List<string>(); 
        for (int columnIndex = 0; columnIndex <= rdr.FieldCount - 1; columnIndex++) 
        { 
         curr_result.Add(rdr.GetString(columnIndex)); 
        } 
        results.Add(curr_result); 
       } 
      } 
     } 
     catch (MySqlException ex) 
     { 
      Console.WriteLine(ex.Message); 
      return null; 
     } 
     finally 
     { 
      if (rdr != null) 
      { 
       rdr.Close(); 
      } 

      if (conn != null) 
      { 
       conn.Close(); 
      } 

     } 
     return results; 
    } 
} 

該類返回2維列表供以後使用。

以我的模型類,我添加一個解析器方法:

public class AtsPlatform 
{ 
    public string Name { get; set; } 
    public string RequestNumber { get; set; } 
    public Int32? NumberOfFail { get; set; } 
    public Int32? NumberOfTestCase { get; set; } 
    public Int32? NumberOfFailWithCR { get; set; } 

    public void Parse(string name, string requestNumber, string numberOfFail, string numberOfTestCase, string numberOfFailWithCR) 
    { 
     Int32 temp; 

     this.Name = name; 
     this.RequestNumber = requestNumber; 
     this.NumberOfFail = (Int32.TryParse(numberOfFail, out temp)) ? Int32.Parse(numberOfFail) : 0; 
     this.NumberOfTestCase = (Int32.TryParse(numberOfTestCase, out temp)) ? Int32.Parse(numberOfTestCase) : 0; 
     this.NumberOfFailWithCR = (Int32.TryParse(numberOfFailWithCR, out temp)) ? Int32.Parse(numberOfFailWithCR) : 0; 
    } 
} 

溶液#2(b)中:原始查詢使用ExecuteStoreCommand

public List<AtsPlatform> GetAtsPlatformByName(string atsPlatformName) 
    { 
     List<AtsPlatform> atsPlatforms = null; 
     string stm = String.Format("SELECT RequestNumber, NumberOfFail, NumberOfTestCase, NumberOfFailWithCR FROM {0}", atsPlatformName); 

     atsPlatforms = new List<AtsPlatform>(); 
     foreach (AtsPlatform ats in ctx.ExecuteStoreQuery<AtsPlatform>(stm)) 
      { 
       atsPlatforms.Add(ats); 
      } 

     return atsPlatforms; 
    } 

溶液#3:存儲過程

我創建了一個存儲過程,這裏是代碼:

DELIMITER $$ 

CREATE PROCEDURE `UnionAtsTables`() 
BEGIN 

DECLARE atsName VARCHAR(10); 
DECLARE atsIndex INT; 

SET atsIndex = 1;  
SET @qry = ''; 

WHILE atsIndex > 0 DO 

    SET atsName =concat('ATS',atsIndex); 
    IF sf_is_table(atsName) = 1 THEN 
     Set @temp_qry = CONCAT('SELECT *, ''', atsName ,''' As TestPlatform FROM ', atsName, ' WHERE RequestNumber <> '''''); 
     If @qry = '' THEN 
      SET @qry = @temp_qry; 
     ELSE 
      SET @qry = CONCAT(@qry, ' UNION ', @temp_qry); 
     END IF; 
    ELSE 
     SET atsIndex = -1; 
    END IF; 

    SET atsIndex = atsIndex + 1; 

END WHILE; 

DROP TABLE IF EXISTS ats_all; 
SET @CreateTempTableQuery = CONCAT('CREATE TEMPORARY TABLE ats_all AS ', @qry ,''); 
PREPARE stmt1 FROM @CreateTempTableQuery; 
EXECUTE stmt1; 
DEALLOCATE PREPARE stmt1; 

ALTER TABLE ats_all DROP COLUMN ExecOrder; 
ALTER TABLE ats_all ADD ExecOrder INT PRIMARY KEY AUTO_INCREMENT; 
ALTER TABLE ats_all auto_increment = 0; 

END 

這是我在網上找到的函數,用來檢查db是否存在於表中。

DELIMITER $$ 

CREATE FUNCTION `sf_is_table`(`in_table` varchar(255)) RETURNS tinyint(4) 
BEGIN 
/** 
* Check if table exists in database in use 
* 
* @name sf_is_table 
* @author Shay Anderson 08.13 <http://www.shayanderson.com> 
* 
* @param in_table (table name to check) 
* @return TINYINT (1 = table exists, 0 = table does not exist) 
*/ 

     # table exists flag 
     DECLARE is_table BOOLEAN DEFAULT FALSE; 

     # table count 
     DECLARE table_count INT DEFAULT 0; 

     # database name 
     SET @db = NULL; 

     # set database name 
     SELECT 
      DATABASE() 
     INTO 
      @db; 

     # check for valid database and table names 
     IF LENGTH(@db) > 0 AND LENGTH(in_table) > 0 THEN 

      # execute query to check if table exists in DB schema 
      SELECT COUNT(1) INTO table_count 
      FROM information_schema.`TABLES` 
      WHERE TABLE_SCHEMA = @db 
        AND TABLE_NAME = in_table; 

      # set if table exists 
      IF table_count > 0 THEN 
        SET is_table = TRUE; 
      END IF; 

     END IF; 

     RETURN is_table; 
END 

結論:

謝謝大家對你的建議。 我決定使用解決方案#2,因爲它不會像解決方案#3那樣對數據庫性能產生太多影響,並且不需要像解決方案#1那樣重新設計數據庫。