webForumDet fria alternativet

Name value collection med wilson ORM?

19 svar · 648 visningar · startad av maqe

maqeMedlem sedan dec. 2003824 inlägg
#1

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?

emissionMedlem sedan dec. 19996 721 inlägg
#2

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.

maqeMedlem sedan dec. 2003824 inlägg
#3

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.

emissionMedlem sedan dec. 19996 721 inlägg
#4

Du får visa lite mer kod

maqeMedlem sedan dec. 2003824 inlägg
#5

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;
}
emissionMedlem sedan dec. 19996 721 inlägg
#6

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);
	}	
}
maqeMedlem sedan dec. 2003824 inlägg
#7

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;
            }
maqeMedlem sedan dec. 2003824 inlägg
#8

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 ...

emissionMedlem sedan dec. 19996 721 inlägg
#9

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;
}
maqeMedlem sedan dec. 2003824 inlägg
#10

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?

emissionMedlem sedan dec. 19996 721 inlägg
#11

Använd den senaste versionen

maqeMedlem sedan dec. 2003824 inlägg
#12

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?

emissionMedlem sedan dec. 19996 721 inlägg
#13

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;	
		}
	}
}
maqeMedlem sedan dec. 2003824 inlägg
#14

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;
}
}
emissionMedlem sedan dec. 19996 721 inlägg
#15

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.

maqeMedlem sedan dec. 2003824 inlägg
#16

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.

maqeMedlem sedan dec. 2003824 inlägg
#17

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?

emissionMedlem sedan dec. 19996 721 inlägg
#18

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.

maqeMedlem sedan dec. 2003824 inlägg
#19

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?

maqeMedlem sedan dec. 2003824 inlägg
#20

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 :)

137 ms totalt · 3 externa anrop · v20260731065814-full.30151723
0 ms — hämta forumlista (cache)
0 ms — hämta statistik (cache)
134 ms — hämta tråd, inlägg och bilagor (db)