Diskuze: mscorlib - chyba
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Člen
Zobrazeno 9 zpráv z 9.
//= Settings::TRACKING_CODE_B ?> //= Settings::TRACKING_CODE ?>
V předchozím kvízu, Test znalostí C# .NET online, jsme si ověřili nabyté zkušenosti z kurzu.
Už chápu kde je problém, můj projekt je cílený na net.framework 4.5 - změnil sem cíl na 4.0 a metoda nyní nefunguje...
Tak sem aktuálně nahradil ...
MappingAttribute[] attributes = modelProperties[i].GetCustomAttributes<MappingAttribute>(true).ToArray();
Tímto:
MappingAttribute[] attributes = Array.ConvertAll(modelProperties[i].GetCustomAttributes(typeof(MappingAttribute), true).ToArray(), s => (MappingAttribute)s);
Aplikace nyní funguje - ale příjde mi, že došlo ke zpomalení...
Ake je to spomalenie? O 20, o 50%? Je to spomalenie citelne?
Osobne by som skor pouzil pristup cez SqlDataAdapter s Fill funkciou do
DataSetu. Nasledne for (!) cyklus nad datarow, v kazdom cykle vytvorit
instanciu, zjistit properties, pak atributy.
V ramci 'SetValue' nemusis pouzivat ChangeType, framework si to pretypuje
automaticky.
Skus to cele rozbit na mensie kusy kodu, tj. do viacej riadkov. Bude to
citatelnejsie ako ta tvoja nova implementacia.
Ale to je iba rada.
Hodne uspechov.
M.
K chybě samotné: nasimulovat se mi to asi nepodaří, ani jsem se o to nepokoušel. Ale z hlášky usuzuji, že chyba opravdu není přímo v tvém kódu.
Ale měl bych připomínku k metodě MapToClass. Předpokládám, že tato je
volána opakovaně pro každý záznam v readeru. A pokaždé vytváříš
instance entit a zjišťuješ attributy pomocí reflexe. Tento postup je
značně nehospodárný. Osobně bych investoval čas do napsání metody, jež
pomocí DynamicMethod zrychlí celý process.
A pokud by byl DynamicMethod příliš velký kanón, pak alespoň nějak
cacheovat zjištěné metainformace o readeru a properties.
To spíš vypadá, že nemají aktualizovaný .NET, takže to nenajde tu knihovnu.
Ahoj myslíš, že bys mohl více rozvést variantu cacheování?
No zkusme:
class Product
{
public int Id { get; set; }
}
public void Load()
{
using (System.Data.SqlClient.SqlDataReader dr = cmd.ExecuteReader())
{
MapInfo mi = GetMapInfo<Product>(dr);
while (dr.Read())
{
Product obj = MapToClass<Product>(dr, mi);
}
}
}
MapInfo GetMapInfo<TEntity>(System.Data.IDataReader dr) where TEntity : class,new()
{
Type entityType = typeof(TEntity);
return new MapInfo
{
Constructor = entityType.GetConstructor(Type.EmptyTypes),
Properties = entityType.GetProperties().Select(x=> {
string colName;
MappingAttribute attribute = x.GetCustomAttributes<MappingAttribute>(true).FirstOrDefault();
return attribute == default(MappingAttribute) || (colName=attribute.ColumnName)!=null
? null
: new MapPropertyInfo { PropertyInfo = x,FieldIndex=dr.GetOrdinal(attribute.ColumnName) };
}).Where(x=>x!=null)
};
}
static object[] _paramLess = new object[0];
TEntity MapToClass<TEntity>(System.Data.SqlClient.SqlDataReader reader, MapInfo mi) where TEntity : class, new()
{
TEntity returnedObject = (TEntity)mi.Constructor.Invoke(_paramLess); //lepsi nez Activator.CreateInstance, jelikoz ten musi ten konstruktor taky hledat a my jej hledali jen jednou
System.Reflection.PropertyInfo pi;
foreach (MapPropertyInfo mpi in mi.Properties)
(pi=mpi.PropertyInfo).SetValue(returnedObject, ChangeType(reader[mpi.FieldIndex], pi.PropertyType));
return returnedObject;
}
class MapInfo
{
internal System.Reflection.ConstructorInfo Constructor;
internal IEnumerable<MapPropertyInfo> Properties;
}
class MapPropertyInfo
{
internal System.Reflection.PropertyInfo PropertyInfo;
internal int FieldIndex;
}
Napsal jsem to hodně horkou jehlou, nechtělo se mi s tím moc hrát. Věřím, že i přesto je záměr jasný.
Další možnost: V method Load se dá dále "MapInfo mi" cacheovat podle TEntity a cmd, tam už to nechám na tobě.
A ani teď si neodpustím doporučení na runtime kompilaci za použití DynamicMethod (vyšší dívčí) nebo Roslyn (to se vážně dá).
Ještě jsem si našel chyby:
class Product
{
[Mapping("pk")]
public int Id { get; set; }
}
MapInfo GetMapInfo<TEntity>(System.Data.IDataReader dr) where TEntity : class,new()
{
Type entityType = typeof(TEntity);
return new MapInfo
{
Constructor = entityType.GetConstructor(Type.EmptyTypes),
Properties = entityType.GetProperties().Select(x=> {
string colName;
MappingAttribute attribute = x.GetCustomAttributes<MappingAttribute>(true).FirstOrDefault();
return attribute == default(MappingAttribute) || (colName=attribute.ColumnName)!=null
? null
: new MapPropertyInfo { PropertyInfo = x,FieldIndex=dr.GetOrdinal(attribute.ColumnName) };
}).Where(x=>x!=null).ToArray() //bez tohohle ToArray by to byl průšvih, pročpak asi?
};
}
Zobrazeno 9 zpráv z 9.