2010年9月12日日曜日

プロコン2010-1その8

ユーザの削除画面。
ユーザを削除すると、そのユーザに紐づく書籍を他の人に移管するかシステムから削除するようにするため、ちょっと考慮が必要でした。


で、DACは、前回書いたUserInfo.csなので今回は省略して、
UI(~/Admin/DeleteUser.aspx)から

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="DeleteUser.aspx.cs" Inherits="Library.Admin.DeleteUser"
MasterPageFile="~/Admins.Master" StylesheetTheme="Standard" %>

<asp:Content ID="Content1" runat="server" ContentPlaceHolderID="ContentPlaceHolder1">
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
<br />
削除対象のユーザを選択してください。<asp:RadioButtonList ID="RadioButtonList1" runat="server" DataSourceID="ObjectDataSource1"
DataTextField="UserName" DataValueField="UserName">
</asp:RadioButtonList>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="GetAllData"
TypeName="Library.DAC.UserInfo"></asp:ObjectDataSource>
<br />
書籍の引継ぎユーザを指定してください。<asp:DropDownList ID="DropDownList1" runat="server" DataSourceID="ObjectDataSource1"
DataTextField="UserName" DataValueField="UserName" AppendDataBoundItems="True">
<asp:ListItem Value="">引き継ぎ無し</asp:ListItem>
</asp:DropDownList>
<asp:Button ID="Button1" runat="server" Text="Button" OnClick="Button1_Click" />
</asp:Content>



次にコードビハインド

using System;
using System.Web.Security;
using System.Web.UI;
using Library.DAC;

namespace Library.Admin
{
public partial class DeleteUser : LibPage
{
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = "";
}

protected void Button1_Click(object sender, EventArgs e)
{
Membership.DeleteUser(RadioButtonList1.SelectedValue);
UserInfo.InheritBookOwner(RadioButtonList1.SelectedValue, DropDownList1.SelectedValue);
UserInfo.DeleteUser(RadioButtonList1.SelectedValue);
Page.DataBind();
Label1.Text = "削除が完了しました";
}
}
}



本当は、ACIDの一貫性を保つために、UserInfo.InheritBookOwner()と、UserInfo.DeleteUser()を連続したよびだしし、トランザクションスコープをくくったUserInfoのメソッドで用意するべきだったけど、まいいかぁ。

プロコン2010-1その7

今回は、ユーザの変更の画面。
DataSetのコードは省略し、DACと、UIのコードを。
まずは、DAC(~/DAC/UserInfo.cs)から。

using System.Collections.Generic;
using System.Web.Security;
using Library.DataSet;
using Library.DataSet.LibraryDataSetTableAdapters;
namespace Library.DAC
{
public static class UserInfo
{
public static LibraryDataSet.UsersDataTable GetAllData()
{
LibraryDataSet.UsersDataTable dt = new LibraryDataSet.UsersDataTable();
using (UsersTableAdapter ta = new UsersTableAdapter())
{
dt = ta.GetData();
foreach (MembershipUser msu in Membership.GetAllUsers())
{
if ((dt.Select("UserName='" + msu.UserName + "'")).Length == 0)
{
dt.AddUsersRow(msu.UserName, string.Empty, false, false);
ta.Update(dt);
}
}
dt = ta.GetData();
foreach (LibraryDataSet.UsersRow ur in dt)
{
ur.AdminRoleFlag = Roles.IsUserInRole(ur.UserName, "Admins");
ur.UserRoleFlag = Roles.IsUserInRole(ur.UserName, "Users");
}
return dt;
}
}
public static void Update(string userName, string information, bool adminRoleFlag, bool userRoleFlag)
{
using (UsersTableAdapter ta = new UsersTableAdapter())
{
ta.Update(information, userName);
}
if (adminRoleFlag && !Roles.IsUserInRole(userName, "Admins"))
{
Roles.AddUserToRole(userName, "Admins");
}
else if (!adminRoleFlag && Roles.IsUserInRole(userName, "Admins"))
{
Roles.RemoveUserFromRole(userName, "Admins");
}
if (userRoleFlag && !Roles.IsUserInRole(userName, "Users"))
{
Roles.AddUserToRole(userName, "Users");
}
else if (!userRoleFlag && Roles.IsUserInRole(userName, "Users"))
{
Roles.RemoveUserFromRole(userName, "Users");
}
}
public static void InheritBookOwner(string oldOwner, string newOwner)
{
using (BookOwnerTableAdapter ta = new BookOwnerTableAdapter())
{
if (string.IsNullOrEmpty(newOwner))
{
ta.DeleteByUserName(oldOwner);
}
else
{
ta.InheritBookOwner(newOwner, oldOwner);
}
}
}
public static void DeleteUser(string userName)
{
using (UsersTableAdapter ta = new UsersTableAdapter())
{
ta.Delete(userName);
}
}
public static LibraryDataSet.UsersDataTable GetDataFirstByGivenUser(string GivenUserName)
{
using(UsersTableAdapter ta=new UsersTableAdapter())
{
return ta.GetDataFirstByGivenUserName(GivenUserName);
}
}
}
}



ユーザ変更のコード部分(~/Admin/ModifyUser.aspx.cs)


<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="ModifyUser.aspx.cs" Inherits="Library.Admin.ModifyUser"
MasterPageFile="~/Admins.Master" StylesheetTheme="Standard" %>

<asp:Content ID="Content1" runat="server" ContentPlaceHolderID="ContentPlaceHolder1">
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
<asp:GridView ID="GridView1" runat="server" DataKeyNames="UserName" AutoGenerateColumns="False"
DataSourceID="ObjectDataSource1" OnRowUpdated="GridView1_RowUpdated" AllowPaging="True"
AllowSorting="True" CellPadding="4" ForeColor="#333333" GridLines="None">
<RowStyle BackColor="#FFFBD6" ForeColor="#333333" />
<Columns>
<asp:CommandField ShowEditButton="True" />
<asp:BoundField DataField="UserName" HeaderText="ユーザ名" ReadOnly="True" SortExpression="UserName" />
<asp:BoundField DataField="Information" HeaderText="ユーザ情報" SortExpression="Information" />
<asp:CheckBoxField DataField="AdminRoleFlag" HeaderText="管理者権限"
SortExpression="AdminRoleFlag" />
<asp:CheckBoxField DataField="UserRoleFlag" HeaderText="ユーザ権限"
SortExpression="UserRoleFlag" />
</Columns>
<FooterStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />
<PagerStyle BackColor="#FFCC66" ForeColor="#333333" HorizontalAlign="Center" />
<SelectedRowStyle BackColor="#FFCC66" Font-Bold="True" ForeColor="Navy" />
<HeaderStyle BackColor="#990000" Font-Bold="True" ForeColor="White" />
<AlternatingRowStyle BackColor="White" />
</asp:GridView>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server" SelectMethod="GetAllData"
TypeName="Library.DAC.UserInfo" UpdateMethod="Update">
<UpdateParameters>
<asp:Parameter Name="userName" Type="String" />
<asp:Parameter Name="information" Type="String" />
<asp:Parameter Name="adminRoleFlag" Type="Boolean" />
<asp:Parameter Name="userRoleFlag" Type="Boolean" />
</UpdateParameters>
</asp:ObjectDataSource>
</asp:Content>



最後に、コードビハインド

using System;
using System.Web.Security;

namespace Library.Admin
{
public partial class ModifyUser : LibPage
{
protected void Page_Load(object sender, EventArgs e)
{
Label1.Text = "";
}

protected void GridView1_RowUpdated(object sender, System.Web.UI.WebControls.GridViewUpdatedEventArgs e)
{
Label1.Text = "更新しました";
}
}
}

プロコン2010-1その6

asp.netの開発では、たとえ1人で作る個人的なプログラムであっても
プログラム開発効率を上げるためにある程度の決め事をしておきます。
(まあ設計というほどのものではないですが。)
たとえばこんな感じ。

A)画面デザインと共有パーツやロジックを複数のアセンブリ(DLLやexe)に分けず、1本のアセンブリで作成する。
 →Visual Studioのプロジェクトは1本。
B)プログラムソースコード群を以下のカテゴリに分ける。
・画面デザイン((UI)1画面内で判断できる画面固有のロジックも含む。フォルダを切らない。)
・ビジネスロジック(DACとBCは分けない。全てDACフォルダに格納する。ファイルアクセスがあればここで行う。)
・データベースアクセス(DBに対するSQL発行。全てDataSetフォルダで行う。)
上記のカテゴリは、隣接するカテゴリのみアクセスを許す。(画面デザインからストレージアクセスへの直呼び出しは不可)
上記のカテゴリのプログラムは、自分より上のカテゴリの構造を前提としてはいけない。(このビジネスロジックを呼び出すためには、呼び出し元がこうなっていなければならないとかはNG)
上記のカテゴリ間の複雑な構造のデータインタフェース(BEC)は、データセットやデータテーブルを用いる。
※データセットやテーブルっていうのは、.netのなかの、ado.netの機能で、データベースやテーブルをメモリ上で実装したものです。
ま、たんに決め事です。

で、データセット作成から、ソリューションエクスプローラで、"DataSet"というフォルダを作って、このフォルダを右クリック、追加でデータセットを作成する。
今回は、Library.xsdという名前で作成しています。
Library.xsdをダブルクリックし、編集画面で、右クリック→追加→DataTableを選択。DataTable1と表示されている部分を左クリックしRolesと変更。
その後、列の追加を行いRoleNameという列を追加。追加した列をクリックし、プロパティ(表示されていなければF4で表示させる。)で、文字列であることを確認する。
これでLibrary.DataSet.LibraryDataSetというクラスの内部クラスで、RolesDataTableクラスが作成される。
なお、Library.DataSet.LibraryDataSetの最初のLibraryは、現プロジェクト名で、次のDataSetは、プロジェクトに作ったフォルダの名前です。
で、RoleDataTableについては、TableAdapterを作っていません。
RoleDataTableへのデータ投入は、ビジネスロジックで行います。
~/DAC/RoleInfo.csの作りは、こんな感じ。これが前回の記事で指定したRoleInfoの内容です。


using System.Web.Security;
using Library.DataSet;

namespace Library.DAC
{
public static class RoleInfo
{
public static LibraryDataSet.RolesDataTable GetAllRole()
{
LibraryDataSet.RolesDataTable dt = new LibraryDataSet.RolesDataTable();
foreach (string s in Roles.GetAllRoles())
{
dt.AddRolesRow(s);
}
return dt;
}
}
}