I dom flesta exemplen jag sett med wilsons or mapper så användes en IList för en collection av objekt men jag skulle vilja kunna hänta ut ett object ur en lista med namn t.ex mittobjekt["Name"]. Hur gör man detta?
Name value collection med wilson ORM?
19 svar · 648 visningar · startad av maqe
Wilson ORM är inte så bra på detta, men du borde kunna använda GetObject("Name") på ObjectSet för ändamålet. Om du verkligen vill använda syntaxen mittobjekt["Name"] så får du skapa en wrapper-klass som du stoppar in ditt ObjectSet i och mappar om...
public MinWrapperKlass<TKey,TValue> : IDictionary<TKey,TValue>
{
private ObjectSet<TValue> _set;
public MinWrapperKlass(ObjectSet<TValue> set)
{
_set=set;
}
public TValue this[TKey key]
{
get
{
return _set.GetObject(key);
}
}
//...och resten av metoderna som behövs för att uppfylla interface-kontraktet
}
..eller så bygger du helt sonika om ObjectSet-klassen från källkoden för ORMapper och lägger till den saknade metoden.
Jag förstår nog inte vart wrapperklassen kommer till användning.
Idag hämtar jag t.ex ett objekt såhär
public static Data GetData(int id) {
return Manager.Engine.GetObject<Data>(id);
}
och sedan när jag får mitt Data objekt så vilja kunna skriva ut ett värde i ett underliggande objekts IList som hämtas och fylls mha arv så jag använder aldrig något ObjectSet.
Du får visa lite mer kod
Nedan är min Dataklass och den innehåller en IList med Propertys för mitt Data objekt. IListen innehåller i sin tur ett Property objekt som har namn och värde. När jag sedan har mitt Data objekt så skulle jag vilja kunna hämta ut värdet på en property genom att skriva MittDataObjekt["PropertyNamn"]. I själva verket skulle jag vilja att or mappern använde en annan collection än IList för lagring av objekt som som mitt dataobjekt har via arv i databasen.
public class Data {
public string Name {
get { return _name; }
set { _name = value; }
}
private string _name;
public IList Propertys {
get { return _propertys; }
}
private IList _propertys;
}
IList är bara ett interface, så collectionen är av någon annan typ, antagligen ObjectSet.
Om det bara är syntaxen du vill åt så (ändrade ordningen lite, eftersom jag inte gillar deklareringar som kommer efter användande)
public class Data {
private string _name;
private IList _properties;
public string Name {
get { return _name; }
set { _name = value; }
}
public IList Properties {
get { return _properties; }
}
public VärdeTyp this[string propertyName]
{
//Kod som hämtar propertyvärdet
//Eventuellt:
ObjectSet set=(ObjectSet) this.Properties;
return (VärdeTyp)set.GetObject(propertyName);
}
}
collectionen innehåller objekt av typen PropertyData.
Såhär skulle man kunna göra men det känns inte rätt och det borde finnas ett bättre sätt att göra det på.
public string this[string index] {
get {
foreach (PropertyData propertyData in _propertys) {
if (index == propertyData.PropertyObject.Name)
return propertyData.Value;
}
return null;
}
Jag tror att du var rätt ute från början med att typa om IList.
Dock verkar det som att man ska använda IObjectSet istället och sedan använda GetObject(object objectKey) ... dock vet jag inte vad som är objektets key hehe ...
maqe skrev:
Dock verkar det som att man ska använda IObjectSet istället och sedan använda GetObject(object objectKey)
Ja, det är ju typ det jag sagt hela tiden.... :)
dock vet jag inte vad som är objektets key
Det förutsätter att det finns en primärnyckel.
En annan variant, som åtminstone cachar resultatet
Dictionary<string,PropertyData> _propertyDict;
public string this[string propertyName]
{
get
{
PropertyData data=PropertyDict[propertyName];
return (data==null) ? null : data.Value;
}
}
private Dictionary<string,PropertyData> PropertyDict
{
if (_propertyDict==null)
{
_propertyDict=new Dictionary<string,PropertyData>();
foreach (PropertyData propertyData in _propertys)
{
_propertyDict[propertyData.PropertyObject.Name]=propertyData;
}
}
return _propertyDict;
}
emission skrev:
Ja, det är ju typ det jag sagt hela tiden.... :)
Det förutsätter att det finns en primärnyckel.
En annan variant, som åtminstone cachar resultatet
Dictionary<string,PropertyData> _propertyDict; public string this[string propertyName] { get { PropertyData data=PropertyDict[propertyName]; return (data==null) ? null : data.Value; } } private Dictionary<string,PropertyData> PropertyDict { if (_propertyDict==null) { _propertyDict=new Dictionary<string,PropertyData>(); foreach (PropertyData propertyData in _propertys) { _propertyDict[propertyData.PropertyObject.Name]=propertyData; } } return _propertyDict; }
Vilken metod skulle du föredra att använda?
Använd den senaste versionen
Ok, tack för hjälpen och tipsen. Om jag vill kunna sätta min min Property["propertyname"] så borde väl den bästa metoden vara att typa om IList till IObjectSet och använda GetObject och det förutsätter ju att PropertyName i databasen är primärnyckeln, eller har du något bättre förslag?
Jag antar att det inte passar din domän särskilt bra att göra propertyName till primärnyckel, så i stället bör man kunna wrappa in set-metoden mot den underliggande IList:en (som är ett ObjectSet). Ta gärna bort all publik access till IList:en, så att det inte finns två vägar in.
public string this[string propertyName]
{
get
{
PropertyData data=PropertyDict[propertyName];
return (data==null) ? null : data.Value;
}
set
{
if (PropertyDict.ContainsKey(propertyName))
{
PropertyDict[propertyName].Value=propertyName;
}
else
{
PropertyData data=//skapa ny PropertyData
data.PropertyObject.Name=propertyName;
_propertys.Add(data);
PropertyDict[propertyName]=data;
}
}
}
Jag tänker mig att bara kunna sätta sådana propertys som redan finns i min IList för Data objektet så else satsen kan vi hoppa över. Känns inte som att den modellen kan fungera eftersom jag bara sätter värdet i Dictionaryn men hur får man sedan värdet att sparas när jag sedan sparar mitt Data objekt? Borde man inte behöva sätta value på propertydata objektet i IList kollektionen? Så som jag har det idag så loopar jag även där igenom alla propertydata tills jag hittar rätt och sätter sedan value på rätt objekt men det känns lika dåligt som min tidigare hämtning av värdet.
Se nedan:
set {
foreach (PropertyData propertyData in _propertyDataPages) {
if (propertyName == propertyData.PropertyObject.Name)
propertyData.Value = value;
}
}
maqe skrev:
Jag tänker mig att bara kunna sätta sådana propertys som redan finns i min IList för Data objektet så else satsen kan vi hoppa över.
Oki
maqe skrev:
Känns inte som att den modellen kan fungera eftersom jag bara sätter värdet i Dictionaryn men hur får man sedan värdet att sparas när jag sedan sparar mitt Data objekt? Borde man inte behöva sätta value på propertydata objektet i IList kollektionen?
Det är precis det som händer. Dictionaryt är bara en referenslista. Det är samma Property-instanser som returneras.
maqe skrev:
Så som jag har det idag så loopar jag även där igenom alla propertydata tills jag hittar rätt och sätter sedan value på rätt objekt men det känns lika dåligt som min tidigare hämtning av värdet.
Min lösning gör samma sak, men den behöver bara loopa en gång, oavsett hur många properties som hämtas, och tack vare lazy-propertyn (PropertyDict) så görs det bara om propertyvärden verkligen hämtas.
När jag försöker sätta värdet på en property så är alltid antalet propertydata i PropertyDict 0 av någon anledning.
Såhär ser koden ut för att spara ett Dataobjekt.
protected void Save_Click(object sender, ImageClickEventArgs e) {
Data data = CurrentData;
data["TestProperty"] = "Lorem ipsum ..."
Manager.Engine.PersistChanges(data, PersistDepth.ObjectGraph);
}
Och det här är ju koden för att hämta och sätta värdet från PropertyDict
public string this[string propertyName] {
get {
if (PropertyDict.ContainsKey(propertyName))
return PropertyDict[propertyName].Value;
return String.Empty;
}
set {
if (PropertyDict.ContainsKey(propertyName))
PropertyDict[propertyName].Value = value;
}
}
private Dictionary<string, PropertyData> PropertyDict {
get {
if (_propertyDict == null) {
_propertyDict = new Dictionary<string, PropertyData>();
foreach (PropertyData propertyData in _propertyDataPages) {
_propertyDict[propertyData.PropertyObject.Name] = propertyData;
}
}
return _propertyDict;
}
}
private Dictionary<string, PropertyData> _propertyDict;
Detta borde fungera väl? Men som sagt PropertyDict innehåller aldrig något objekt när jag försöker sätta propertyn men när jag hämtar så fungerar det som de ska.
Om propertyn inte har något värde så finns den inte med. Det kanske var det du menade med din else sats tidigare? Alla Data objekt använder en mall som ska ha dessa propertys så vad är anledningen till att dom bara finns om dom har ett värde?
Är det lazy loading som gör att man får detta beteendet?
maqe skrev:
Men som sagt PropertyDict innehåller aldrig något objekt när jag försöker sätta propertyn men när jag hämtar så fungerar det som de ska.
Det måste bero på att den underliggande IList:en är tom av någon anledning (ett nytt Data-objekt?). ProperytDict initieras på samma sätt oavsett om det är set eller get.
Japp den underliggande IList:en är tom. Det finns bara propertydata objeckt i IListen om det propertydata.value finns annars existerar den inte av någon anledning?
Jag har nog tänkte lite konstigt här, jag kan bara sätta propertydatat på dom som redan har ett värde i tabellen och med min databasmodell så måste det ju existera en post i databasen för att den ska kunna laddas i IList:en såklart. Tack för hjälpen sålänge emisson :)