---------------------| tanimal |---------------------| animalID || discriminator || furcolour || feathercolour |---------------------public abstract class Animal{ public int AnimalID { get; set; } public string discriminator { get { return GetType().name; } }}public class Bird : Animal{ public string FeatherColour { get; set; }}public class Dog : Animal{ public string FurColour { get; set; }}
正如所料,当通过Dapper的查询方法检索它时,我无法创建抽象类的实例.我希望这会返回一个Animal列表,它们的值是相应的派生类型.
var animals = Connection.query<Animal>("SELECT * FROM tanimal")
我试图增加对此的支持是不成功的.在传入sqlMapper.cs :: GetTypeDeserializer()之前,如果传入的类型是抽象类,那么我将类型替换为以下方法中返回的类型:
static Type GetDerivedType(Type abstractType,IDataReader reader){ var discriminator = abstractType.GetProperty("discriminator"); if (discriminator == null) throw new InvalIDOperationException("Cannot create instance of abstract class " + abstractType.Fullname + ". To allow dapper to map to a derived type,add a discriminator fIEld that stores the name of the derived type"); return Type.GetType((string)reader["discriminator"]);}
但是,此时看起来还没有打开读取器,因此当没有数据存在时无效尝试读取失败.
这是正确的方法吗?有没有任何努力在其他地方支持这个?
解决方法 你可以使这个工作,但它不如使用Dapper的默认行为与单独的表.需要为每一行调用GetDeserializer,这意味着它需要在内部发生(reader.Read())
通过修改queryImpl< T>你可以达到你想要的效果.假设你得到的结果是:
var results = connection.query<Animal>("SELECT * FROM tanimal");
然后是queryImpl< T>的try {}块的开头.将会:
try{cmd = command.SetupCommand(cnn,info.ParamReader);if (wasClosed) cnn.open();// We can't use SequentialAccess any more - this will have a performance hit.reader = cmd.ExecuteReader(wasClosed ? CommandBehavior.CloseConnection : CommandBehavior.Default);wasClosed = false; // You'll need to make sure your typePrefix is correct to your type's namespacevar assembly = Assembly.GetExecutingAssembly();var typePrefix = assembly.Getname().name + ".";while (reader.Read()){ // This was already here if (reader.FIEldCount == 0) //https://code.Google.com/p/dapper-dot-net/issues/detail?ID=57 yIEld break; // This has been moved from outsIDe the while int hash = GetColumnHash(reader); // Now we're creating a new DeserializerState for every row we read // This can be made more efficIEnt by caching and re-using for matching types var discriminator = reader["discriminator"].ToString(); var convertToType = assembly.GetType(typePrefix + discriminator); var tuple = info.Deserializer = new DeserializerState(hash,GetDeserializer(convertToType,reader,-1,false)); if (command.AddToCache) SetqueryCache(IDentity,info); // The rest is the same as before except using our type in ChangeType var func = tuple.Func; object val = func(reader); if (val == null || val is T) { yIEld return (T)val; } else { yIEld return (T)Convert.ChangeType(val,convertToType,CultureInfo.InvariantCulture); }}// The rest of this method is the same
这将使该方法仅适用于鉴别器字段,因此您可能想要创建自己的queryImpl< T>如果你需要这个与其他查询正常工作.此外,我不能保证这将在每种情况下都有效,只测试两行,每种类型一个 – 但这应该是一个很好的起点.
总结以上是内存溢出为你收集整理的c# – 在小巧玲珑中查询抽象模型全部内容,希望文章能够帮你解决c# – 在小巧玲珑中查询抽象模型所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)