使用ObjectDataSource和DataObjectTypeName,如何处理只有Id参数的删除方法?

时间:2009-05-27 01:40:25

标签: c# .net asp.net vb.net objectdatasource

如果我有一个ObjectDataSource设置,如:

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

以及使用以下方法的数据/业务对象:

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

如何让objectdatasource将Delete方法与不是Employee对象的参数一起使用?

如果无法做到这一点,推荐的替代架构是什么?

修改

为了澄清,我想在我的数据/业务对象上使用方法签名,如上所示,但是如果我尝试允许使用DataObjectTypeName将Employee对象传递给某些方法,那么我似乎失去了有一些方法只需要一个整数id。

如果我不使用DataObjectTypeName,那么我必须将所有方法参数放在ObjectDataSource中并更改数据/业务对象上的方法以匹配,这似乎是一个糟糕的设计选择,因为当Employee对象改变时我将不得不更新这些方法。 有更好的架构吗?

8 个答案:

答案 0 :(得分:1)

这是解决方案,它对我来说是更新操作然后删除比更新更容易:

  1. 创建Class以传递参数。 例如:我正在为Usermaster表传递参数: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. 我将objectdatasource绑定到formview以进行更新uperation.Set objectdatasource如下:

    <asp:ObjectDataSource ID="odsUser" runat="server" 
        TypeName="MMCTaxINTLXMLValidation.UserBLL"
        SelectMethod="GetUserRoleByUserId" 
        DataObjectTypeName="MMCTaxINTLXMLValidation.UserMasterDT"  
        OldValuesParameterFormatString="original_{0}" 
        UpdateMethod="UpdateUserWithTransaction" onupdated="odsUser_Updated">        
        <SelectParameters>
            <asp:QueryStringParameter  Name="iUId" QueryStringField="UserId" Type="Int32" 
                DefaultValue="-1" />
        </SelectParameters>
        <UpdateParameters>
            <asp:Parameter  Name="UserId" Type="Int32" ConvertEmptyStringToNull="true" />
            <asp:Parameter  Name="RoleId" Type="Int32" ConvertEmptyStringToNull="true" />
            <asp:Parameter  Name="Firstname" Type="String"  ConvertEmptyStringToNull="true" />
            <asp:Parameter  Name="Lastname" Type="String" ConvertEmptyStringToNull="true" />       
            <asp:Parameter  Name="BirthDate" Type="String" ConvertEmptyStringToNull="true" />
            <asp:Parameter  Name="MMCEmail" Type="String" ConvertEmptyStringToNull="true" />
            <asp:Parameter  Name="Homecontact" Type="String" ConvertEmptyStringToNull="true" />
            <asp:Parameter  Name="Officecontact" Type="String" ConvertEmptyStringToNull="true" />
            <asp:Parameter  Name="Cellcontact" Type="String" ConvertEmptyStringToNull="true" />
            <asp:Parameter  Name="Logon" Type="String" ConvertEmptyStringToNull="true" />
            <asp:Parameter  Name="Password" Type="String" ConvertEmptyStringToNull="true" />
            <asp:Parameter  Name="PasswordQ1" Type="String" ConvertEmptyStringToNull="true" />
            <asp:Parameter  Name="PasswordA1" Type="String" ConvertEmptyStringToNull="true" />               
        </UpdateParameters>
    </asp:ObjectDataSource>
    

    注意此处没有任何输出参数

  3. 现在,IN U R BLL在更新方法中,传递并返回UserMasterDT作为输入和输出。不要通过单独的参数和不可接受的参数。写代码如:

    此处我正在进入和离开UserMasterDT

    [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;
    }
    
  4. 然后在aspx.cs页面中读取UserMasterDT的属性,如下所示:

    if (e.Exception == null)
    {
        UserMasterDT tempuser = (UserMasterDT) e.ReturnValue;
        lblMsg.Text = "Record Updated : " + tempuser.iRecUpdated.ToString();
    }
    
  5. 我的存储过程是:

    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
    

  6. 希望这可以帮助您完成任何您需要做的事情。 sairam

答案 1 :(得分:0)

当你将objectdatasource绑定到一个控件时,你应该能够根据你尝试绑定的数据得到一个 Id (在你的例子中,我会假设是EmployeeId),然后你可以将其设置为删除参数。

在这里查看msdn example

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

答案 2 :(得分:0)

您必须从对象数据源声明中删除DataObjectTypeName="Employee"。此属性获取并设置ObjectDataSource控件用于delete方法中的参数的类的名称。

   <asp:ObjectDataSource 
        ID="ObjectDataSource1" 
        runat="server" 
        InsertMethod="Insert" 
        UpdateMethod="Update"
        DeleteMethod="Delete" 
        TypeName="EmployeeDB">
        <deleteparameters>
            <asp:parameter name="EmpID" type="Int32" />
        </deleteparameters>
    </asp:ObjectDataSource>

答案 3 :(得分:0)

即使您按如下方式实施课程:

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

当您尝试删除时,您将只获取绑定到对象上'DataKeys'的字段,例如ID。

*在旁注中,在插入或更新后返回对象允许DataView更新行。

我记得它工作的方式是你可以配置你的ObjectDataSource将参数传递给db层 OR 传递对象,而不是两者的组合。

这意味着可以使用手动配置的参数进行以下操作:

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

答案 4 :(得分:0)

我不久前使用LinqToSql进行类似的项目。我有两种不同类型的删除方法:

    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();
    }

..您可以看到DeleteDisconnected方法旨在接受来自'ObjectDataSource'的整个实体对象。我正在使用

ConflictDetection="CompareAllValues"

..和

OldValuesParameterFormatString="original_{0}"

..对于这种情况的'ObjectDataSource'上的参数,但您可能不需要这样做。我想我仍然可以通过上述方法获得并发异常 - 这是我当时想要的 - 利用LinqToSql内置的冲突检测/并发功能。

您的体系结构取决于您在应用程序的较低层中处理数据等的方式(在问题中您似乎没有提到太多)。传递业务对象而不是作为方法参数的所有字段绝对是更成熟的设计。但偶尔(对于删除函数)只需要int ID ..但它取决于您的底层实现。

答案 5 :(得分:0)

对象方法签名变量名称必须与对象属性名称完全匹配,并且它将起作用。例如,编辑*也不要忘记DataKeyNames属性

public class EmployeeDB
{
    public int ID{get;set;}
    public string Name {get;set;}
    public ing Age{get;set;}

    //both these would work
    public void Insert(Employee emp)
    public void Insert(string Name,int Age)

    //both these would work
    public void Update(Employee emp)
    public void Update(int ID,string Name,int Age)

    //works
    public void Delete(Employee emp)

    //WONT work
    public bool Delete(int empId)
    //will work
    public void Delete(int ID)

}

<asp:ObjectDataSource 
    ID="ObjectDataSource1" 
    runat="server" 
    DataObjectTypeName="Employee"
    InsertMethod="Insert" 
    UpdateMethod="Update"
    DeleteMethod="Select" 
    TypeName="EmployeeDB" 
     DataKeyNames="ID">
<DeleteParameters>
    <asp:Parameter Name="ID" Type="Int32" />
</DeleteParameters>
</asp:ObjectDataSource>

答案 6 :(得分:0)

得到这个问题希望解决这个确切的困境,并在尝试其他答案提出后,得出结论你只是不能混合方法。你的所有方法(插入,更新,删除)都有:

  • 单个自定义类参数(其类型在DataObjectTypeName属性中指定)或
  • 每个属性的参数列表(在每个<InsertParameters><UpdateParameters><DeleteParameters>中指定)。

使用单参数版本和Insert方法仅使用Delete参数不能使用Int32方法。当我读到ObjectDataSource documentation清楚地说:

时,我的发现得到了证实
  

设置DataObjectTypeName属性和ObjectDataSource时   控件与数据绑定控件相关联,即方法   每个必须由InsertMethod和DeleteMethod属性指定   有一个在。中指定的类型的参数   DataObjectTypeName属性。

唯一的例外可能是Update方法,它可以有一个或两个参数,具体取决于ConflictDetection属性,但这是一个完全不同的故事。

我遇到的唯一解决方案是重载Delete方法来欺骗ObjectDataSource,并在内部使用Delete参数调用Int32方法:

// This method gets called by the ObjectDataSource
public Int32 Delete(MyCustomClass foo)
{
    // But internally I call the overloaded method
    Delete(foo.Id);
}

public Int32 Delete(Int32 id)
{
    // Delete the item
}

答案 7 :(得分:0)

如果使用DataObjectTypeName而不是单独的参数,则您使用的业务对象将起作用。您只需要添加DataKeyNames =“Id”,其中Id是您的绑定控件中的主键字段,如GridView或其他内容。

它将填充您的类型参数,在您的“Employee”类型中,“Id”值可用于删除实体。