Avatar of tRi11
tRi11
Flag for United Kingdom of Great Britain and Northern Ireland asked on

Generic custom collections, iBATIS.NET and Unity.

Hi,

I'm trying to use a generic custom collection interface (to support injection with Microsoft Patterns and Practices Unity) in a class O/R mapped with iBATIS.NET.  Does anyone know if this is possible and if so how to do it?

I have an IDataItemCollection<T> interface that I map to SqlDataItemCollection<T> which extends CollectionBase.  I want to use the IDataItemCollection<T> in my classes so I can swap SqlDataItemCollection<T> with other classes that extend the interface through Unity.  The iBATIS.NET mapping file can reference the concrete class directly as there won't be one without the other.

Below I have included a very simplified example of the code, database and mappings.  I'm completely new to iBATIS.NET and really just want to prove its use at the moment, so please re-jig the mapping XML as necessary.

Many thanks,

Paul
public interface IDataItem
{
	object Id { get; set; }
}
 
public class DataItem : IDataItem
{
	public object Id { get; set; }
}
 
public interface IDataItemCollection<T> : ICollection where T : IDataItem
{
	// Various Getters and Setters
...
}
 
public class SqlDataItemCollection<T> : CollectionBase, IDataItemCollection<T> where T : DataItem
{
	public SqlDataItemCollection() { }
	public SqlDataItemCollection(T injType) { }
 
	// Getters and Setters to implement interfaces
...
}
 
public class Foo : DataItem
{
	public Foo(IDataItemCollection<Bar> bars)
	{
		Bars = bars;
	}
 
	public IDataItemCollection<Bar> Bars { get; set; }
}
 
public class Bar : DataItem { }
 
 
 
-- SQL Server 2005 Database
 
CREATE TABLE Foo
(
	Id bigint IDENTITY(1,1)
)
 
CREATE TABLE Bar
(
	Id bigint IDENTITY(1,1)
)
 
CREATE TABLE FooBar
(
	FooId bigint,
	BarId bigint
)
 
 
 
<!-- iBATIS.NET mapping.xml -->
 
<resultMaps>
	<resultMap id="FooResult" class="Foo">
		<result property="Id" column="Id"/>
		<result property="Bars" column="Id" select="SelectBarsInFoo" lazyLoad="false"/>
	</resultMap>
 
	<resultMap id="BarResult" class="Bar">
		<result property="Id" column="Id"/>
	</resultMap>
</resultMaps>
 
<statements>
	<select id="SelectFoo" resultMap="FooResult">
		SELECT Id
      		FROM Foo
	</select>
 
	<select id="SelectBarsInFoo" parameterClass="long" resultMap="BarResult" listClass="SqlDataItemCollection`1[Bar]" >
		SELECT Bar.Id
		FROM Bar
		JOIN FooBar ON Bar.Id = FooBar.BarId
		WHERE FooBar.FooId = #value#
	</select>
</statements>

Open in new window

.NET ProgrammingC#

Avatar of undefined
Last Comment
tRi11

8/22/2022 - Mon
MogalManic

I wouldn't  bother with trying to get the ibatis mapper to support "getter" methods using your custom collection.  Just implement the constructor:
    public SqlDataItemCollection(IEnumberable<T> itemList) :base(itemList)  { }


And in your DAO method, just do:
   public SqlDataItemCollection<foo>  GetFooList()
   {
             SqlDataItemCollection<foo> fooList=new SqlDatItemCollection<foo>(mapper.QueryForList<foo>(null));
            return foo;
   }
   

tRi11

ASKER
Hi,

Thanks for this, do I assume then that it is not possible to make iBATIS.NET populate the list from the mapping file, i.e. when a query is run to get Foo it automatically populates all the associated Bars as well?

At the moment I'm just trying to get a feel for iBATIS.NET and so am not worried about performance issues or lazy loading etc.  However, I do want to be able to retrieve a particular Foo fully populated with all associated Bars.

Thanks,

Paul
tRi11

ASKER
Hi,

The problem seems to simply relate to the fact I need to use an interface instead of a concrete class.  Replacing IDataItemCollection<Bar> with SqlDataItemCollection<Bar> in Foo causes everything to work as expected, unfortunately I then loose the ability to swap the concrete classes with Unity.

Is this a limitation of iBATIS.NET?

Thanks,

Paul
All of life is about relationships, and EE has made a viirtual community a real community. It lifts everyone's boat
William Peck
MogalManic

Looks like the closest you can get with ibatis is using the listClass attribute on the <select> element.  (as you already asked in another forum: http://stackoverflow.com/questions/603808/using-ibatis-net-with-generic-custom-collection-interfaces-and-unity)

but there is nothing limiting you to downgrade the return value back to its implementing interface in the DAO method:
public IDataItemCollection<T>  GetFooList<T>()
  {
     SqlDataItemCollection<T> fooList=new SqlDatItemCollection<T>(mapper.QueryForList<foo>(null));
     return foo;
  }
 
or if your select element is using the ListClass attribute
public IDataItemCollection<T>  GetFooList<T>()
  {
     return (SqlDatItemCollection<T>)(mapper.QueryForList<foo>(null));
  }

Open in new window

tRi11

ASKER
Hi,

Thanks again.  Yes the listClass attribute does exactly what I want but unfortunately it only appears to work on concrete classes.  The problem is that I do not want a dependency to SqlDataItemCollection<T>, this should be resolved by Unity at runtime.  I also need for the Foo object to be returned fully populated, I know I can perform a QueryForList to populate the Bars collection of Foo but this then relies on a specific call in the DAO not just the appropriate mapping in the XML file.

It kind of looks like I am trying to do something that can't be done with iBATIS.NET and I either need to look at a different ORM or review the domain model.

Thanks,

Paul
ASKER CERTIFIED SOLUTION
MogalManic

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
tRi11

ASKER
Hi,

Thanks for the suggestion, I think you're probably right, it looks like creating a custom implementation is going to be the only way of getting it to work the way I want it to.  I was hoping the solution would be fairly straight forward, at the moment I'm not prepared to spend the time trying to fit iBATIS.NET around my domain model when there are so many other ORM's out there which may fit better.

I will leave this question open for now as I may come back to it if nothing works out better.  If I decide to go with another ORM I will award you the points as my question was for iBATIS.NET and although I'm not prepared to try it now, I do believe your suggestion offers the best chance of success.

Thanks again,

Paul
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
tRi11

ASKER
Hi,

I have decided to drop IBATIS.NET as the main ORM for my project.  I have opted instead for a lightweight attribute based ORM that works perfectly with my current domain design and goals for the project as a whole.  Anyway, thanks for your help, I will award you the points as I'm sure your solution was the way to go had I decided to stick to IBATIS.NET.

Thanks,

Paul
tRi11

ASKER
I did not choose to adopt the solution myself instead opting for an alternate ORM, however the solution appears to be the best option if sticking with IBATIS.NET.