我正在寻找在运行时通过字符串变量选择的表上执行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");
我可以使用“switch”但这会使代码不易扩展,并且每当创建新的“ats(N + 1)”时都需要更新。
我2天的研究让我无处可去,但却回到了零点。我很困惑。
请帮助!谢谢!
答案 0 :(得分:1)
而不是反射,如何使用SqlQuery函数?
所以
List<AtsPlatform> GetAtsPlatformByName(int index)
{
using (var ctx = new Entities())
{
return ctx.Database.SqlQuery<AtsPlatform>("SELECT * FROM dbo.ats" + index)
.ToList();
}
}
此外,对于在Database对象上使用SqlQuery方法的实体没有更改跟踪(在您的情况下我可以这样做,因为AtsPlatform类只包含原始属性)。
对于更改跟踪,您需要使用DbSet SqlQuery方法,并且可能需要混合一些反射。
答案 1 :(得分: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。
答案 2 :(得分: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;