Avatar billede codecow Nybegynder
25. november 2011 - 15:47 Der er 3 kommentarer og
1 løsning

lave en omvendt join i nhibernate

Hej

Jeg vil gerne finde alle entities i en tabel hvor de opfylder et antale kriterier og hvor deres id'er IKKE optræder i en anden tabel. Dvs en omvendt join.

Nedenstående funktion fungerer men jeg ville helst lave det i et hug mod databasen

Er der nogen der har en smart metode i nhibernate?

Mvh

Henrik




        /// <summary>
        /// Find alle patienter der er overført til ORTO behandling, siden vi
        /// søgte sidst, så vi kan oprette dem i det eksterne system
        /// </summary>
        private IList<Patient> FindNewOrtoReferredPatients(ISession session, DateTime fromTime, DateTime toTime)
        {
            IList<Patient> retVal = new List<Patient>();
            var patientRepository = new PatientRepository(session);
            var patienter = (from x in patientRepository.GetQuery()
                where x.VisiterTilOrto == true
                    &&
                    (
                        (x.Log.OprettetTid > fromTime && x.Log.OprettetTid < toTime)
                    ||
                        (x.Log.RettetTid > fromTime && x.Log.RettetTid < toTime)
                    ) 
                orderby x.Fornavne
                select x).ToList()
                ;

            // Check mod overført listen 'OrVisiteret', og find ud af om der skal oprettes eller opdateres
            // Kun hvis de skal oprettes tilføjes de til retVal
            var ortoVisiteretRepository = new OrtoVisiteretRepository(session);
            var ortoVisiterede = ortoVisiteretRepository.GetAll();
            bool allreadyCreated = false;

            // FIXME: det her er noget lort. Det har en worst case O-tid på N^2 - det må sgu da kunne laves i DB direkte
            foreach (var p in patienter)
            {
                foreach (var o in ortoVisiterede)
                {
                    if (p.Id == o.Patient.Id)
                    {
                        allreadyCreated = true;
                        break;
                    }
                }
                if(!allreadyCreated)
                {
                    retVal.Add(p);
                }
                allreadyCreated = false;
            }
            return retVal;
        }
Avatar billede Syska Mester
25. november 2011 - 15:54 #1
Hvordan ser dine tables ud og hvordan er din mapning i NH?

Du burde jo bare kunne lave en left join og så kun tage de result som har den ene del til null.

mvh
Avatar billede arne_v Ekspert
26. november 2011 - 01:42 #2
WHERE NOT IN som SQL, HQL og LINQ:

using System;
using System.Collections.Generic;
using System.Linq;

using MySql.Data.MySqlClient;

using NHibernate;
using NHibernate.Cfg;
using NHibernate.Linq;

namespace E
{
    public class Person
    {
        public virtual string Navn { get; set; }
        public virtual string Adresse { get; set; }
        public virtual int Postnr { get; set; }
    }
    public class Post
    {
        public virtual int Postnr { get; set; }
        public virtual string Bynavn { get; set; }
    }
    public class Program
    {
        public static void TestDataReader()
        {
            using(MySqlConnection con = new MySqlConnection("Server=localhost;Database=test;User Id=root;Password="))
            {
                con.Open();
                MySqlCommand sel = new MySqlCommand("SELECT navn,adresse,postnr FROM person WHERE postnr NOT IN (SELECT postnr FROM post)", con);
                MySqlDataReader rdr = sel.ExecuteReader();
                while(rdr.Read())
                {
                    string navn = (string)rdr[0];
                    string adresse = (string)rdr[1];
                    int postnr = (int)rdr[2];
                    Console.WriteLine(navn + " " + adresse + " " + postnr);
                }
                rdr.Close();
            }

        }
        public static void TestNHibernateHQL()
        {
            Configuration cfg = new Configuration();
            cfg.Configure("hibernateconfig.xml");
            cfg.AddXmlFile("mappings.xml");
            ISessionFactory sf =  cfg.BuildSessionFactory();
            using(ISession s = sf.OpenSession())
            {
                IList<Person> lst = s.CreateQuery("FROM Person AS p WHERE p.Postnr NOT IN (SELECT p2.Postnr FROM Post AS p2)").List<Person>(); 
                foreach(Person p in lst)
                {
                    Console.WriteLine(p.Navn + " " + p.Adresse + " " + p.Postnr);
                }
            }
        }
        public static void TestNHibernateLINQ()
        {
            Configuration cfg = new Configuration();
            cfg.Configure("hibernateconfig.xml");
            cfg.AddXmlFile("mappings.xml");
            ISessionFactory sf =  cfg.BuildSessionFactory();
            using(ISession s = sf.OpenSession())
            {
                IList<Person> lst = (from p in s.Query<Person>() where !s.Query<Post>().Select(p2 => p2.Postnr).Contains(p.Postnr)  select p).ToList<Person>();
                foreach(Person p in lst)
                {
                    Console.WriteLine(p.Navn + " " + p.Adresse + " " + p.Postnr);
                }
            }
        }
        public static void Main(string[] args)
        {
            TestDataReader();
            TestNHibernateHQL();
            TestNHibernateLINQ();
            Console.ReadKey();
        }
    }
}
Avatar billede codecow Nybegynder
29. november 2011 - 13:50 #3
Hej

Tak for hjælpen. Jeg har efter at have prøvet mig lidt frem og tilbage fundet frem til den her løsning som ikke er streng baseret. :)

Hvis der er nogen der vil ave point så smid et svar :)


        /// <summary>
        /// Find alle patienter der er overført til ORTO behandling, siden vi
        /// søgte sidst, så vi kan oprette dem i det eksterne system
        /// </summary>
        private static IList<Patient> FindNewOrtoReferredPatients(ISession session, DateTime fromTime, DateTime toTime)
        {
            var ortoCriteria = DetachedCriteria.For<OrtoVisiteret>()
                .SetProjection(Projections.Distinct(Projections.Property<OrtoVisiteret>(x => x.Patient)))
                ;

            var patientCriteria = DetachedCriteria.For<Patient>()
                .Add(Restrictions.Where<Patient>(x => x.VisiterTilOrto == true))
                .Add(Restrictions.Disjunction()
                    .Add<Patient>(x => x.Log.OprettetTid.IsBetween(fromTime).And(toTime))
                    .Add<Patient>(x => x.Log.RettetTid.IsBetween(fromTime).And(toTime)))
                .Add(Subqueries.NotExists(ortoCriteria))
                ;

            var retVal = patientCriteria.GetExecutableCriteria(session).List<Patient>();

            return retVal;
        }
Avatar billede arne_v Ekspert
30. november 2011 - 03:11 #4
NHibernat er stort.

Udover HQL og LINQ er der ogsaa Criteria.

:-)

Og et svar hvis du syntes.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
IT-kurser om Microsoft 365, sikkerhed, personlig vækst, udvikling, digital markedsføring, grafisk design, SAP og forretningsanalyse.

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester