2009-07-24 14 views
5

OK, vì vậy tôi có trường cơ sở dữ liệu kiểu char (1) có một số lượng nhỏ mã trạng thái có thể (ví dụ: 'F' = Không, 'U' = Không xác định, v.v.). Tôi muốn có một lớp C# enum tương ứng với các trạng thái này. Tôi có thể làm:Làm thế nào để thực hiện C# enum cho liệt kê char (1) trường cơ sở dữ liệu?

public enum StatusCode : byte { 
    Unknown = (byte) 'U', 
    Failure = (byte) 'F', 
    // etc. 
} 

Cho đến nay rất tốt. Nhưng trong DataTable được trả về từ cơ sở dữ liệu, các giá trị cột là các phiên bản System.Data.SqlTypes.SqlString. Rõ ràng là một số vấn đề chuyển đổi từ một chuỗi C# (hoặc thậm chí là C# char) thành một byte C# (vì C# char thực sự là một điểm mã UTF-16). Nhưng trong trường hợp này tôi biết các giá trị bị ràng buộc với một tập hợp nhỏ và mã nên ném một ngoại lệ nếu một giá trị nằm ngoài tập hợp này đi qua.

Với ý nghĩ đó, cách tốt nhất để làm điều này là gì? Có an toàn để đúc từ một SqlString đến một byte? Convert.ToByte() có tốt hơn không? Nó sẽ được tốt hơn để chỉ đơn giản là sử dụng một chuyển đổi/trường hợp xây dựng để crosswalk các giá trị vào enum?

Tôi đang tìm cách "tốt nhất" để làm điều này, không chỉ về mặt nhận kết quả phù hợp mà còn cho sự rõ ràng của mã. Tôi cho rằng tôi cũng có thể chỉ sử dụng một số hằng số như

public const char UnknownStatus = 'U'; 
public const char FailureStatus = 'F'; 

Nhưng tôi muốn sử dụng enum nếu có thể. Có suy nghĩ gì không?

Chỉnh sửa: Để làm rõ những gì tôi muốn làm với điều này, tôi hy vọng sẽ sử dụng các giá trị này thường xuyên trong suốt mã của tôi. Ví dụ: tôi muốn có thể thực hiện những việc như:

public void DoSomething(StatusCode currentStatus) { 
    if(currentStatus == StatusCode.Failure) { 
     throw new SomeException(); 
    } 

    switch(currentStatus) { 
     case StatusCode.Unknown: 
      // do something 
      break; 
    } 
} 

Và cứ tiếp tục như vậy. Tôi đặc biệt muốn tránh những thứ như:

public void DoSomething(char currentStatus) { 
    if(currentStatus == 'F') { 
     // do something 
    } 
} 

Vì trong trường hợp này tôi đang sử dụng số tiền cho "số ảo" khắp nơi. Đặc biệt, điều này sẽ làm cho việc di chuyển sang một số hệ thống gắn cờ nhà nước khác hầu như không thể. Điều đó có ý nghĩa?

+0

Xem thêm http://stackoverflow.com/questions/1167927/syncing-referential-integrity-tables-and-enums và http://stackoverflow.com/questions/1015058/enum-storage-in- trường cơ sở dữ liệu và nói chung, http://stackoverflow.com/search?q=enum%20database&tab=newest –

Trả lời

5

Có thể là đối tượng "không đổi"?

public sealed class StatusCode { 
    private char value; 

    public static readonly StatusCode Unknown = new StatusCode('U'); 
    public static readonly StatusCode Failure = new StatusCode('F'); 

    private StatusCode(char v) { 
     value = v; 
    } 

    public override string ToString() { 
     return value.ToString(); 
    } 

} 

Sau đó, sau trong mã của bạn, bạn có thể sử dụng nó như một enum: StatusCode.Unknown. Bạn cũng có thể cung cấp một phương thức nội bộ để 'phân tích cú pháp' một giá trị nhận được thành một đối tượng của StatusCode.

+2

bạn cũng nên cung cấp sự bình đẳng ngầm để cung cấp so sánh chính xác cho các giá trị nhất định ... –

+0

Đúng vậy! : D – Fernando

+0

OK, tôi nghĩ đây là tuyến đường tôi sẽ đi. Thật không may, trường hợp báo cáo vẫn không hoạt động như tôi muốn, nhưng ít nhất là mọi thứ khác. (Giống như kiểu enum Java kiểu cũ!) –

0

Nếu bạn đang ở trên .NET 2.0 trở lên, bạn có thể thực hiện điều này bằng cách sử dụng từ điển chung:

Dictionary<char,string> statusCode = new Dictionary<char,string>(); 
statusCode.Add('U', "Unknown"); 
statusCode.Add('F', "Failure"); 

hoặc cách khác:

Dictionary<char,StatusCode> statusCode = new Dictionary<char,StatusCode>(); 
statusCode.Add('U', StatusCode.Unknown); 
statusCode.Add('F', StatusCode.Failure); 

và bạn có thể truy cập vào chuỗi đại diện cho một mã được cung cấp như vậy:

string value = statusCode['A']; 

hoặc

StatusCode myCode = statusCode['A']; 

v.v. Bạn sẽ phải điền vào từ điển đó từ các giá trị cơ sở dữ liệu, hoặc từ một số loại tệp cấu hình hoặc một cái gì đó.

Marc

0

Điều gì đó như thế có phù hợp với bạn không?

public Enum StatusCode : int{ 
    [StringValue("U")] 
    Unknown =0, 
    [StringValue["F"] 
    Failuer=1 
} 
+0

là phần Thuộc tính StringValue của khung .NET. Tìm kiếm nhanh trên Google sẽ bật lên một vài lớp theo tên đó nhưng không có gì trên MSDN – STW

+0

http://weblogs.asp.net/stefansedich/archive/2008/03/12/enum-with-string-values-in-c.aspx có một ví dụ thực hiện đầy đủ. – JasonTrue

1

Skip để chỉnh sửa bạn đã thử này (mà không làm việc như bạn đã kiểm tra và nhận xét):

public enum StatusCode : char 
{ 
    Failure = 'F', 
    Unknown = 'U', 
    ... 
} 

EDIT - giải pháp đúng
hay này (có thể thậm chí thử với cấu trúc):

public sealed class StatusCode 
{ 
    public static readonly char Failure = 'F'; 
    public static readonly char Unknown = 'U'; 
    ... 
    public char Value { get; set; } 
} 

mã bạn cung cấp sẽ lo k như thế này:

public void DoSomething(StatusCode currentStatus) { 
    if(currentStatus.Value == StatusCode.Failure) { 
     throw new SomeException(); 
    } 

    switch(currentStatus.Value) { 
     case StatusCode.Unknown: 
      // do something 
      break; 
    } 
} 

Nếu bạn không muốn sử dụng Value tài sản mà bạn luôn luôn có thể thực hiện điều hành bình đẳng tuyệt đối giữa StatusCodechar loại. Trong trường hợp đó, mã của bạn sẽ không thay đổi một chút.

+0

Không tốt: trình biên dịch cho: Lỗi Loại byte, sbyte, ngắn, ushort, int, uint, long, hoặc ulong expecte –

+2

Bây giờ, không có lý do gì để mang lại sự thô lỗ vào điều này. ;-) –

+0

^^ Tôi gần như đã bỏ lỡ điều đó! : D – Jagd

0

Nếu bạn có một bảng gọi là StatusCode bao gồm một khóa nguyên nguyên thì bạn có thể sử dụng nó làm định danh của bạn cũng như móc nó vào trong logic của bạn. Và trong trường hợp đó, enum sẽ là thứ tốt nhất để sử dụng. Mặc dù tôi không chắc chắn nếu điều này là khả thi cho bạn.

0

Một lựa chọn là để thiết lập enum của bạn với những cái tên giống với các giá trị trong cơ sở dữ liệu của bạn, chẳng hạn như:

enum StatusCode 
{ 
    /// <summary>Unknown</summary> 
    U = 0, 
    /// <summary>Failure</summary> 
    F, 
    /// <summary>Etc</summary> 
    E 
} 

Sau đó sử dụng một phương pháp tĩnh để chuyển đổi các giá trị char đến một giá trị liệt kê

private StatusCode CharToEnum(string statusCodeChar) 
    { 
     foreach (FieldInfo fi in typeof(StatusCode).GetFields()) 
     { 
      if (fi.Name == statusCodeChar) return (StatusCode)fi.GetValue(null); 
     } 

     return StatusCode.U; 
    } 
0

Ngắn và ngọt ngào người đàn ông của tôi .. Có tất cả mọi thứ bạn cần nó. Bạn không cần phải sử dụng enum vì bạn không cần nó để gán một giá trị nội bộ cho các trạng thái có thể của bạn, bạn đã biết các giá trị cho các trạng thái của bạn.

public sealed class StatusCode 
{ 
    public const string Unknown= "U"; 
    public const string Failure= "F"; 
    public const string Success= "S"; 
}