StrataFrame Forum

BO Constructor

http://forum.strataframe.net/Topic515.aspx

By Daniel Essin - 2/3/2006

Objects that inherit from MicroFour.StrataFrame.Business.BusinessLayer, i.e. BusinessObjects, have 2 overloads on the constructor. The second one takes an IContainer.



How and when is that used?
By StrataFrame Team - 2/6/2006

The second constructor that accepts the IContainer is used when you drop a business object on a form or a user control. The IContainer that gets passed is the "components" collection on the form/user control. This constructor signature is a standard signature used by objects that inherit from Component, MarshalByValueComponent, or MarshalByRefComponent.
By Daniel Essin - 2/7/2006

In a windows service you get some code like:

      private System.ComponentModel.Container components = null;



      public Service1()

      {

         // This call is required by the Windows.Forms Component Designer.

         InitializeComponent();



         // TODO: Add any initialization after the InitComponent call

      }



would there be any point/benefit to passing 'components' to the BO constructor?
By StrataFrame Team - 2/7/2006

Probably... if you drop a business object onto the service within the service designer, then the code generator will automatically call that method... I believe the service will cycle through it's "components" collection and Dispose() of each item when the service shuts down.
By Daniel Essin - 2/8/2006

I'll try it.
By Daniel Essin - 2/8/2006

Tried it...



The error says "The object that the business object has been dropped on must implement MicroFour.StrataFrame.UI.Windows.Forms.IContainerControl.



How do I do that?
By Daniel Essin - 2/8/2006

Tried inheriting from MicroFour.StrataFrame.UI.Windows.Forms.IContainerControl -

got the following errors. Need documentation and/or guidance about how to implement this stuff on non-visual components.



TEST_FaxSending.Form1' does not implement interface member 'MicroFour.StrataFrame.UI.Windows.Forms.IContainerControl.AddObjectToInitOnLoad(MicroFour.StrataFrame.UI.IInitOnFormLoad)'   'TEST_FaxSending.Form1' does not implement interface member 'MicroFour.StrataFrame.UI.Windows.Forms.IContainerControl.AddBusinessObject(MicroFour.StrataFrame.Business.BusinessLayerBase)'   'TEST_FaxSending.Form1' does not implement interface member 'MicroFour.StrataFrame.UI.Windows.Forms.IContainerControl.AddObjectToPreInitOnLoad(MicroFour.StrataFrame.UI.IPreInitOnFormLoad)'   C:\_devel\release.90000\TEST-FaxSending\TEST-FaxSending\Form1.Designer.cs   TEST_FaxSending.Form1' does not implement interface member 'MicroFour.StrataFrame.UI.Windows.Forms.IContainerControl.RemoveBusinessObject(MicroFour.StrataFrame.Business.BusinessLayerBase)'   C:\_devel\release.90000\TEST-FaxSending\TEST-FaxSending\Form1.Designer.cs   
By StrataFrame Team - 2/9/2006

The "components" collection is only used for user interface stuff, and the IContainerControl interface is only also only used for user interface stuff. Since the service you're creating does not have a user interface, I wouldn't worry about trying to implement the IContainerControl interface, and avoid the user of that constructor overload all together.



What I would do is within the "start" method for the service, create your SqlDataSourceItem and add it to the DataSources collection, then create your business objects. Then, within the "stop" method, call Dispose() on the business objects to ensure that resources are released.
By Daniel Essin - 2/9/2006

I've got this code in my service:



//-- Create Business Objects

_Log = new DdmLog();

_Queue = new DdmQueue();

_Log.ParentBusinessObject = _Queue;

_Log.Navigated += new BusinessLayer.NavigatedEventHandler(_Log_Navigated);



and

_Queue.FillPendingItems();

if (_Queue.Navigate(BusinessNavigationDirection.First))

{

do

{

MessageBox.Show(_Log.DocumentTitle);

}

while (_Queue.Navigate(BusinessNavigationDirection.Next));

}

and

void _Log_Navigated(NavigatedEventArgs e)

{

_Log.FillByParentPrimaryKey(_Queue.DocumentID);

}



and

public void FillPendingItems()

{

try

{

//-- Establish locals

SqlCommand loCommand = new SqlCommand();



//-- Create the command

loCommand.CommandText = "SELECT * FROM dbo.DdmQueue ORDER BY DttmQueued DESC";

loCommand.CommandType = CommandType.Text;



//-- Execute the command

this.FillDataTable(loCommand);

}

catch (ApplicationException ex)

{

Console.WriteLine(ex.Message);

}

}



and I get this error

"An error occurred while creating a new DataLayer for the business object."



I guess I'm still lost.
By Gary C Wynne - 2/9/2006

Hi Daniel

Just a SWAG; maybe the connection information is missing? This is one reason that the datalayer may not be able to be created. I had a similar situation when I created BOs outside the general context of a standard SF application. Check the inner exception (if provided) on the error and see what it indicates.

HTH

-=Gary

By Trent L. Taylor - 2/10/2006

Daniel,

More than likely it has to do with the connection.  Has any BO populated at all in this current service?  It would help to see the inner exception.  You can create a recursive loop on the catch while the InnerException is not NULL and print each exception to the control.  This would give a better idea.

Did you add a connection to the MicroFour.StrataFrame.Data.DataBasics.DataSources collection anywhere?  Since you are going through a service rather than a WinForm, you are responsible for setting up the connection within the service.  If you have not added a connection, then this is more than likely the problem.  You can add a connection as follows:

MicroFour.StrataFrame.Data.DataBasics.DataSources.Add("","server=localhost;Integrated Security=SSPI;Database=MyDataBase;")

By Daniel Essin - 2/10/2006

I did:

System.Data.SqlClient.SqlConnectionStringBuilder loBuilder = new System.Data.SqlClient.SqlConnectionStringBuilder();

loBuilder.DataSource = _DdmServer;

loBuilder.InitialCatalog = _DdmDatabase;

loBuilder.UserID = _DdmLogin;

loBuilder.Password = _DdmPassword;



//-- Create a new data source item

//loNewDB = new SqlDataSourceItem(_DdmDatabase, loBuilder.ToString());

//-- Add the new database to the data source collection

DataLayer.DataSources.Add(new SqlDataSourceItem(_DdmDatabase, loBuilder.ToString()));





The innerException said something like "the DataSourceKey[] cannot be null."
By Trent L. Taylor - 2/10/2006

There is the problem.  When you create the SqlDataSourceItem, your first parameter is NULL.  The first parameter should be an empty string unless you are going to have more than one data source on the back end.  For example:

MicroFour.StrataFrame.Data.SqlDataSourceItem("","server=localhost;integrated security=SSPI;database=MyDatabase;")

Notice the first parameter is just an empty string.  By default all business objects DataSourceKey property is empty, which would be like the example above.  If you are going to have more than one type of connection, you may specify another connection and give a unique DataSourceKey (first parameter above) and then you would put that key name in the DataSourceKey property of the business object.  That would tell the business object which data connection to use.

I think this is where you are having the problem.  When using the WinForms and the Connection String Wizard, we manage this piece for you automatically.