views:

2319

answers:

5

If I have an ObjectDataSource setup like:

<asp:ObjectDataSource 
    ID="ObjectDataSource1" 
    runat="server" 
    DataObjectTypeName="Employee"
    InsertMethod="Insert" 
    UpdateMethod="Update"
    DeleteMethod="Select" 
    TypeName="EmployeeDB">
</asp:ObjectDataSource>

and a data/business object with methods like:

public class EmployeeDB
{
    public void Insert(Employee emp)
    public int Update(Employee emp)
    public bool Delete(int id)
}

How do I get the objectdatasource to use the Delete method with the parameter that is not an Employee object?

If this is not possible, what is the recommended alternative architecture?

Edit:

To clarify, I want to use the method signature on my data/business object as shown above, however if I try to allow an Employee object to be passed into some of the methods using DataObjectTypeName, then I seemingly lose the ability to have some methods take just an integer id for instance.

If I do not use the DataObjectTypeName, then I have to place all the method parameters in the ObjectDataSource and change the methods on the data/business object to match, this seems like a bad design choice because as the Employee object changes I will have to update each of these methods. Is there a better architecture?

A: 

When you bind your objectdatasource to a control, you should be able to get an Id (in your example, I would assume EmployeeId) based on the data you try to bind to, and then you can set this as a delete parameter.

check out msdn example here.

<asp:objectdatasource
          id="ObjectDataSource1"
          runat="server"
          selectmethod="GetAllEmployees"
          deletemethod="DeleteEmployee"
          ondeleting="NorthwindEmployeeDeleting"
          ondeleted="NorthwindEmployeeDeleted"
          typename="Samples.AspNet.CS.EmployeeLogic">
          <deleteparameters>
            <asp:parameter name="EmpID" type="Int32" />
          </deleteparameters>
        </asp:objectdatasource>
J.W.
When I tried that I received an error somewhere along the lines of "a delete method that takes Employee as a parameter cannot be found". Asp.Net complains if it cannot find a method with the appropriate signature.
Laz
You have to define this method in the code behind file. Alternativley, you can try to declare this in object data source property grid(by press F4), it will create the function signature for you.
J.W.
Thanks for the response, I have attempted to clarify the question above.
Laz
A: 

You have to remove DataObjectTypeName="Employee" from your object data source declaration. This property gets and sets the name of the class that the ObjectDataSource control uses for a parameter in your delete method.

   <asp:ObjectDataSource 
        ID="ObjectDataSource1" 
        runat="server" 
        InsertMethod="Insert" 
        UpdateMethod="Update"
        DeleteMethod="Delete" 
        TypeName="EmployeeDB">
        <deleteparameters>
            <asp:parameter name="EmpID" type="Int32" />
        </deleteparameters>
    </asp:ObjectDataSource>
Phaedrus
Yes, but then I lose the ability to pass in an Employee object and have to set all of my parameters for each method. How do I use an Employee object parameter for some and not for other methods?
Laz
A: 

Even if you implement your class as follows:

public class EmployeeDB
{
    public Employee Insert(Employee emp)
    public Employee Update(Employee emp)
    public void Delete(Employee emp)
}

You will only get the fields bound to the 'DataKeys' passed through on the object when you try to delete, eg the ID.

*On a side note, returning the object after an Insert or Update allows the DataView to update the row.

The way I remember it working was you can configure your ObjectDataSource to pass through parameters to your db layer OR pass though the objects, NOT a combination of both.

Which means the following would be possible with the manually configured parameters:

public class EmployeeDB
{
    public int Insert(string name, DateTime dob)
    public int Update(int id, string name, DateTime dob)
    public void Delete(int id)
}
Brendan Kowitz
A: 

I was using LinqToSql for a project similar to this a short while ago. I had two different types of delete methods:

    public void DeleteDisconnected(Product original_entity)
    {
        var db = new RmsConcept2DataContext(base.ConnectionString);

        db.Products.Attach(original_entity, false);

        db.Products.DeleteOnSubmit(original_entity);

        db.SubmitChanges();
    }

    public void Delete(int ID)
    {
        var db = new RmsConcept2DataContext(base.ConnectionString);

        Product product = db.Products.Single(p => p.ProductID == ID);

        // delete children
        foreach (Release release in product.Releases)
            db.Releases.DeleteOnSubmit(release);

        db.Products.DeleteOnSubmit(product);

        db.SubmitChanges();
    }

.. you can see the DeleteDisconnected method is designed to accept the whole entity object from the 'ObjectDataSource'. I was using the

ConflictDetection="CompareAllValues"

..and

OldValuesParameterFormatString="original_{0}"

..params on the 'ObjectDataSource' for this case but you may not need to do that. I think i could still get concurrency exceptions on deletes with the above approach - which is what i wanted at the time - to make use of LinqToSql's built in conflict detection/concurrency features.

Your architecture depends on how you handle data, etc in lower layers of your app (which you don't seem mention much about in the question). It is definitely more mature design to pass around the business objects rather than all the fields as method params. But occasionly (for delete functions) only the int ID is necessary.. but it depends on your underlying implementation.

cottsak
A: 

Here is soultion and it is working for me for update operation then delete far easier than update :

  1. Create Class to pass parameter. For Example : I am passing paramter for Usermaster table : UserMasterDT :

    public UserMasterDT(int userid, int roleid, string Firstname, string ) { this.muserid = userid; this.mroleid = roleid; this.mfirstname = Firstname; this.mlastname = Lastname;

    }

    //Here set this prop as DUMMY output variable, that u used everywhere to get   output value
     public int iRecUpdated
     {
         get { return mrecupdated; }
         set { mrecupdated = value; }
     }
    
  2. I am binding objectdatasource to formview for update uperation.Set objectdatasource as follows :

OldValuesParameterFormatString="original_{0}" UpdateMethod="UpdateUserWithTransaction" onupdated="odsUser_Updated">


NOTICE THERE IS NO ANY OUTPUT PARAMTER HERE

  1. Now, IN U R BLL In update method, pass and return UserMasterDT as input and output. DO NOT PASS SEPERATE PARAMETER AND OUT VARAIBLE . Write code like :

HERE I AM PASSING UserMasterDT AS IN AND OUT [System.ComponentModel.DataObjectMethodAttribute(System.ComponentModel.DataObjectMethodType.Update, true)] public UserMasterDT UpdateUserWithTransaction(UserMasterDT tempuser) { int iRecUpdated = -1; Adapter.BeginTransaction();

        try
        {
            string sFlag = "UpdateUserRole";
            int iUserId = tempuser.UserId;
            int iRoleId = tempuser.RoleId;
            string sFirstname = tempuser.Firstname;
            string sLastname = tempuser.Lastname;
            int? iReturnData;


           //THIS OUT IS FROM MY SQL STORED PROCE NOT WITH OBJECTDATASOURCE OUT PARAMETER. IT HAS NOTHING TO DO WITH OBJECT DATA SOUCE.
            Adapter.UpdateUserRole(sFlag,iUserId,iRoleId,sFirstname,sLastname,out iReturnData);                    


            if (iReturnData == 1)
            {
                iRecUpdated = 1;
                this.Adapter.CommitTransaction();
            }
            else if (iReturnData == null)
                iRecUpdated = -1;


            //What ever is return, set it back to UserMasterDT's iRecUpdated prop
            tempuser.iRecUpdated = iRecUpdated;
                     return tempuser;
        }
        catch (Exception ex)
        {
            if (ex != null)
            {
                Adapter.RollbackTransaction();
                //CustomEX objCUEx = new CustomEX(ex.Message, ex);
                ex = null;
                iRecUpdated = -1;    //-1 : Unexpected Error
                //What ever is return, set it back to UserMasterDT's iRecUpdated prop                
                tempuser.iRecUpdated = iRecUpdated;              
                return tempuser;
            }
        }
        finally
        {

            tempuser.iRecUpdated = iRecUpdated;

        }

        //Return tempuser back
        return tempuser;
    }
  1. then in aspx.cs page read property of UserMasterDT as follows :

    if (e.Exception == null) { UserMasterDT tempuser = (UserMasterDT) e.ReturnValue; lblMsg.Text = "Record Updated : " + tempuser.iRecUpdated.ToString();

    }
    
  2. My stored proc is :

set ANSI_NULLS ON

create PROCEDURE [dbo].[UpdateUserRole] ( @sFlag varchar(50), @iUserId int, @iRoleId int, @sFirstname varchar(50), @sLastname varchar(50), @iReturnData int output ) as Begin Declare @errnum as int Declare @errseverity as int Declare @errstate as int Declare @errline as int Declare @errproc as nvarchar(100) Declare @errmsg as nvarchar(4000)

-----------------------
if @sFlag = upper('UPDATEUSERROLE')
begin    
 begin try
  begin tran
   --Update User Master Table
   UPDATE    tblUserMaster
   SET  Firstname = @sFirstname, 
   Lastname = @sLastname,    
   WHERE UserId = @iUserId

   --Update tblUserRolesTran Table
   update  tblUserRolesTran
   set roleid = @iRoleId    
   where Userid = @iUserId

  commit tran -- If commit tran execute then trancount will decrease by 1

  -- Return Flag 1 for update user record and role record
  SET @iReturnData = 1

 end try
 begin catch
  IF @@Trancount > 0  
   -- Get Error Detail In Variable
   Select  @errnum =@@ERROR,
   @errseverity = ERROR_SEVERITY(),
   @errstate = ERROR_STATE(),
   @errline = ERROR_LINE(),
   @errproc = ERROR_PROCEDURE(),
   @errmsg = ERROR_MESSAGE()

   rollback tran

   -- To see print msg, keep raise error on, else these msg will not be printed and dislayed
   print '@errnum : ' + ltrim(str(@errnum ))
   print '@errseverity : ' + ltrim(str(@errseverity))
   print '@errstate : ' + ltrim(str(@errstate))
   print '@errline : ' + ltrim(str(@errline))
   print '@errproc : ' + @errproc
   print '@errmsg : ' + @errmsg

   --Raise error doesn't display error message below 50000
   --So we have to create custom message and add to error table using  sp_addmessage ( so_addmessage is built-in sp)
   --In custom error message we have line number and error message
   Declare @custerrmsg as nvarchar(4000)
   Select @custerrmsg =  'Proc: UpdateUserRole, Line: ' + ltrim(str(@errline)) +  ': ' + @errmsg

   if (@errnum < 50000)
    EXEC SP_ADDMESSAGE @msgnum = 50002, @severity = 16,  @msgtext = @custerrmsg, @replace = 'REPLACE'


   --After adding custom error message we need to raise error
   --Raise error will appear at client (.net application)
   RAISERROR(50002,16,1)   
 end catch
 end
 set nocount off

End


Hope this helps you whatever u need to do. sairam

sairam