永続化前後のクラスの表現について C#

このQ&Aのポイント
  • リレーショナルデータベースを使用し、O/Rマッピングツールを使えない状況で、主キーの変更を考慮したクラスの表現について悩んでいます。
  • 現在のクラスでは、StaffCodeを主キーとして使用していますが、将来変更される可能性があるため、サロゲートキーを使用することを考えています。
  • クラスを分けるべきか、考え方が間違っているのか迷っています。アドバイスをいただけると助かります。
回答を見る
  • ベストアンサー

永続化前後のクラスの表現について C#

ものすごくくだらない質問ですみません。 リレーショナルデータベースを使わざるを得なく、O/Rマッピングツールは使えない状況です。 class Employee があります。 StaffCodeがありますが、将来このコードが重複はありませんが変わる可能性があるので永続化を目的としてこれを主キーとして使えません。 そこで主キーにサロゲートキーを使おうと考えました。 アプリ側で対応するよりもデータベース側でオートナンバーを使います。 一応下記コードでこれから採番する社員と、永続化&採番したあとの社員を表現する事はできます。 しかし同じクラスを使うものなのでしょうか? クラスを分けるべきでしょうか? そもそも考え方がおかしいですか? Class Employee { Public Int Id { get; private set; } Public String Name { get; private set; } Public Int StaffCode { get; private set; } Public Employee(String name, Int staffCode) { this.Name = name; this.StaffCode = staffCode; } Public Employee(Int id, String name, Int staffCode) { this.Id = id; this.Name = name; this.StaffCode = staffCode; } Public Void SetId(Int id) { this.Id = id; } }

noname#220775
noname#220775

質問者が選んだベストアンサー

  • ベストアンサー
  • ques9900
  • ベストアンサー率34% (47/136)
回答No.2

> 一つ気になることがあるのですが、一番変更してはいけないidが >一番変更しやすい設計になっているのは割り切って考えればいいんでしょうか? はい、割りきってしまって良いと思いますよ。 もし何か変更条件を追加したくなった場合には、SetIdに条件を追記すればよいかと。

noname#220775
質問者

お礼

お礼が遅くなって済みませんでした。 インフルエンザにかかって寝込んでました。 ques9900さんも気をつけてくださいね。 割り切って上記方法でやっていきたいと思います。 ありがとうございました。

その他の回答 (1)

  • ques9900
  • ベストアンサー率34% (47/136)
回答No.1

同じクラスで良いと思われます。 従業員の雇用形態が変わるような場合は、 差分を派生クラスにするべきと思いますが、 永続化の有無は全ての従業員に必要な属性と思うので、 基底クラスにidがあれば良いと思います。

noname#220775
質問者

お礼

ありがとうございます。 確かに雇用形態が変わる場合は派生クラスにすべきですよね。 考え方がずれてないようで一安心です。

noname#220775
質問者

補足

一つ気になることがあるのですが、一番変更してはいけないidが一番変更しやすい設計になっているのは割り切って考えればいいんでしょうか? Public Void SetId(Int id) 既にidが設定されていれば例外を投げればいい気もしますが。 そこだけちょっと気持ち悪くて気になっています。 新しく質問すべきかもしれない内容で申し訳ないですが、よろしければアドバイスお願いします。

関連するQ&A

  • C#クラスについて教えてください

    下記通りクラスを作成した場合、プロパティaを配列にできますか? class Class1 { public string a { set; get; } public int b { set; get; } public int c { set; get; } } イメージとしては下記通りにしたいのですが、なかなかうまく行きません。 class Class1 { public Class1(int x) { } public string a[x] { set; get; } public int b { set; get; } public int c { set; get; } } private void Form1_Load(object sender, EventArgs e) { Class1 f = new Class1(2); f.a[0] = "asdf"; f.a[1] = "asdfa"; f.a[2] = "asdfasd"; f.b = 1; f.c = 2; } 初心者なんで、やさしく教えてください。お願いします。

  • C#でレート別に管理するクラスを作りたい

    本の管理をするアプリを作っている時にまた疑問が出てきました。 public class Book { public string Title { get; set; } public string ISBN { get; set; } public Money Money { get; set; } public int Rate { get; set; } public DateTime BuyDate { get; set; } } 本の管理にレートをつけられるようにしようと思っています。 iTunesの★マークのようなものにしたいので1~5の固定です。 つけていないものもあるので0も存在します。 ここでレートを付けている本を、それぞれのレート別にグループに分けたいと思いました。 そこでレート1~レート5までのグループをどのように管理するのがベストというか、どのように考えればいいのでしょうか。 私が考えたのは、グループ別に処理が分かれるのでクラスを作った方がいいと考えたのです。 とりあえず同じ処理もいくつか発生するので public abstract class AbstractRate { public int Value { get; set; } private static BookCollection _bookCollection; //全ての本が入る public BookCollection BookCollection { get { return _bookCollection; } } } みたいな基底クラスを作り public class Star1 :AbstractRate { private BookCollection _books; } から Star5までの似たようなクラスを作り、それぞれのレートのBookコレクションを持たせる形です。 ただこれだと同じようなクラスが増えるだけでものすごく冗長だと思うのです そこでもう一つ思ったのは public class GroupClass { public string GroupName { get; set; } public BookCollection BookCollection { get; set; } } という形でグループ名と本のリストを入れておく形です。 これだとクラスは分かりやすくていいのですが、毎回処理をさせる際にこの名前のグループならこれみたいな処理が必要になる気がして悩んでいます。 実際どのように考えるのがいいのでしょうか? 直接的な回答でなくてもいいのですが、考える材料が欲しいです。 よろしくお願いします。

  • C#でプロパティを使わずXMLにデータを保存したい

    C#を使っているのでC・C++のジャンルでいいのか分からないのですがこちらで質問させて下さい。 現在簡単な本の管理をするアプリを作っています。 プロパティをできるだけ使わずにカプセル化して作っていたのですが、肝心のデータを保存する段階で分からなくなりました。 public class Book { private static int _id_gen; private int _id2; private string _isbn; private string _name; public Book(string isbn, string name) { this._isbn = isbn; this._name = name; } } このようにコンストラクタでデータを渡して get プロパティだけあとで追加するようにしています。 こういうデータを保存する際はまとめて保存するのではなくて List<Book> なんかを foreach で回して1件ずつ保存するといいのでしょうか? 読み込む際は1件ずつ読み込んでクラスに設定していくというのが標準的な考え方ですか? 「C# XML 保存」で検索をかけると XmlSerializer でまとめて保存する事例ばかりでちょっと分からなくなってしまいました。 よろしくお願いします。

  • クラスで永続的な値を持たせたい

    親クラスが保持している値(ここではID)を維持して それぞれの子クラスが利用できるようにしたいのですが、 次のようなやり方だと維持できないようです。 どのようにすればクラスを利用する場合に永続的な値を 持たせることができるのでしょうか? class oya {  var $ID = 0;  function setID($ID) { $this->ID = $ID; }  function getNextID() { return $this->ID + 1; } } class sub1 extends oya {  function sub1 () {$this->setID($this->getNextID());} } class sub2 extends oya {  function sub2 () {$this->setID($this->getNextID());} } $sub1 = new sub1();//←IDが1になる $sub2 = new sub2();//←希望としてはIDが2になってほしいが、IDは1

    • ベストアンサー
    • PHP
  • EF CodeFirst についての質問

    entity framework code first についての質問です。 既存のデータベースから移行するときに詰まってしまいました。お助けください。 複数の外部キーを同テーブルから参照している場合Entityクラスにはどう外部キーを書けばいいのでしょうか? 例 class Store{ public int StoreId {get;set;} public int UserId {get;set;} public int UserId2 {get;set;} * この部分です public virtual User User {get;set;} } class User{ public int UserId {get;set;} public int Name {get;set;} public virtual ICollection<Store> Stores { get; set; } } いろいろ検索して調べてみたのですが解決できませんでした。 よろしくお願いいたします。

  • DAOクラスの使い方

    ある書籍を参考に勉強しております。以下のDAOクラスのデータ追加に関して使い方がわかりません。 サーブレット、もしくはJSPにどのように書けば、DBにデータを追加できるようになるのでしょうか? 宜しく御願い致します。 package chap11_database.sec03; import java.sql.*; import java.util.ArrayList; public class EmployeeDAO { //データベースとの接続に必要な情報を保持するフィールド変数 private final static String DRIVER_URL ="jdbc:mysql://192.168.2.200:3306/satoh" + "?useUnicode=true&characterEncoding=utf8"; private final static String DRIVER_NAME = "com.mysql.jdbc.Driver"; private final static String USER_NAME = "root"; private final static String PASSWORD = "1qaz!QAZ"; //接続メソッド protected Connection createConnection(){ try{ Class.forName(DRIVER_NAME); Connection con = DriverManager.getConnection(DRIVER_URL, USER_NAME, PASSWORD); return con; } catch(Exception e){ e.printStackTrace(); } return null; //例外が発生した場合はnullを返す。 } //切断メソッド protected void closeConnection(Connection con){ try{ con.close(); } catch(Exception ex){ ex.printStackTrace(); } } public ArrayList<Employee> findAll(){ //社員一覧を保持するリスト ArrayList<Employee> list = new ArrayList<Employee>(); Connection con = null; try{ //データベースに接続 con = createConnection(); //データベースにSQL文を送信 String sql = "select * from employee"; Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(sql); while(rs.next()){ int id = rs.getInt("id"); String name = rs.getString("name"); String address = rs.getString("address"); int tel = rs.getInt("tel"); Date birthday = rs.getDate("birthday"); Employee employee = new Employee(id, name, address, tel, birthday); //TO(Employeeオブジェクト)を、社員一覧を保持するリス手に追加 list.add(employee); } //社員一覧を返す。 return list; }catch(Exception e){ e.printStackTrace(); return null; }finally{ //データベースからの切断 closeConnection(con); } } //社員登録メソッド public void create(Employee emp){ Connection con = null; try{ //データベースに接続 con = createConnection(); //データベースにSQL文を送信 String sql = "insert into employee values(?, ?, ?, ? ,?)"; PreparedStatement stmt = con.prepareStatement(sql); stmt.setInt(1, emp.getId()); stmt.setString(2, emp.getName()); stmt.setString(3, emp.getAddress()); stmt.setInt(4, emp.getTel()); stmt.setDate(5, emp.getBirthday()); stmt.executeUpdate(); }catch(Exception e){ e.printStackTrace(); }finally{ //データベースからの切断 closeConnection(con); } } }

    • ベストアンサー
    • Java
  • スレッドセーフ?スレッドアンセーフ?

    Struts2にてスレッドセーフを勉強しており 以下のコードがスレッドセーフなのか、それともスレッドアンセーフなのかご意見を頂きたいと思います。 個人的な意見ですが、インスタンス変数を利用しているためスレッドアンセーフになるのではないかと思いますが間違いございませんでしょうか。 //以下 Struts2 public class InsertProgram extends ActionSupport implements ServletRequestAware{ private Test test = new Test(); private String id; private String name; public class execute(){ id     = request.getParameter("id"); name = request.getParameter("name");        //以下がご意見を頂きたい箇所です。 test.setId(id); test.setName(name); test.insert(); return SUCCESS; } } public class Test{ private String id; private String name; public String getId() { return id; } public String getName() { return name; } public void setId(String id) { this.id = id; } public void setName(String name) { this.name = name; } public class insert() { //割愛致します。 データベースにid 及び name をinsert します。 sql = "Insert into test_db(id , name) ・・・" } }

    • ベストアンサー
    • Java
  • interface プロパティ

    【ケース1】 class Class1 { public string str { get; set; } public int x { get; set; } } 【ケース2】 class Class1 : Class2, Class3 { public string str { get; set; } public int x { get; set; } } interface Class2 { int x { get; set; } } interface Class3 { string str { get; set; } } インターフェースのプロパティの実装をしています、【ケース2】です。 これと【ケース1】ってどこがどう違うのでしょうか?何か同じな感がぬぐえません class2とclass3のプロパティを再定義してるという感がしません。。 実装の仕方がまちがってる場合はご指摘ください。お願いします。

    • ベストアンサー
    • Java
  • ButteflyPersistenceの主キー

    現在O/RマッパーでButteflyPersistenceを使っているのですが、主キーがうまくマッピングできていないらしく更新・削除の処理をすると”No primary key columns for object mapping”というエラーが発生します。主キーを割り当てる方法がございましたらご教授ください。 設定したファイルの内容は以下の通りです。 DBはH2を使っています。 CREATE TABLE user ( ID Identity, NAME varchar(255) default NULL, AGE Integer (2), PRIMARY KEY (ID) ) Userクラス import com.jenkov.db.itf.mapping.AClassMapping; import com.jenkov.db.itf.mapping.AGetterMapping; import com.jenkov.db.itf.mapping.ASetterMapping; @AClassMapping(mappingMode="modify", tableName="user") public class User { @SuppressWarnings("unused") private static final long serialVersionUID = 1L; private int id; private int age; @AGetterMapping(columnName="ID",databaseGenerated=true) public int getId() { return id; } @ASetterMapping(columnName="ID") public void setId(int id) { this.id = id; } private String name; @AGetterMapping(columnName="NAME") public String getName() { return name; } @ASetterMapping(columnName="NAME") public void setName(String name) { this.name = name; } @AGetterMapping(columnName="AGE") public int getAge() { return age; } @ASetterMapping(columnName="AGE") public void setAge(int age) { this.age = age; } }

  • 得点を表示するクラス

    class Tokuten { private int id; private String name; private int eng; private int math; private int sci; Tokuten(int i,String nm,int e,int m,int k) { id=i;name=nm;eng=e;math=m;sci=k; } void show() { System.out.println("("+id+","+name+","+ eng+","+ math+","+ sci+")"); } } public void push(Tokuten tokuten) { if(sp!=tokutens.length) { tokuten.show(); System.out.println("push"); students[sp++]=student; } else { System.out.println("Stack is full"); } } class Sample { public static void main(String[] args) { Stack ss=new Stack(0); ss.push(new Tokuten(1,"Jiko",72,80,68)); (Tokuten)(ss.pop()).show(); } 下記のような得点の表を表示したいのですがうまくいきません set Dataという得点を受け取って各フィールドに格納するやり方が分からないのでエラーばかり出るのだと思います、どなたかソースなどお教えくださると助かります

    • ベストアンサー
    • Java

専門家に質問してみよう