2009-06-25 41 views
16

Tôi hiện đang sử dụng nhà cung cấp ADO.NET của Microsoft cho Oracle (System.Data.OracleClient). Tôi biết rằng nó chắc chắn không phải là nhà cung cấp Oracle tốt nhất có sẵn và rằng nó will soon be deprecated, tôi nên sử dụng ODP.NET của Oracle để thay thế. Lý do tại sao tôi vẫn sử dụng nhà cung cấp MS là vì ODP.NET liên kết các thông số theo vị trí, không theo tên. Điều này thực sự có thể là một PITA khi bạn sử dụng nhiều tham số trong một truy vấn, bởi vì bạn phải cẩn thận để thêm chúng vào đúng thứ tự, mà có thể dễ dàng dẫn đến lỗi. Nó cũng gây phiền nhiễu khi bạn sử dụng các thông số tương tự nhiều lần trong cùng một truy vấn, ví dụ:Tham số truy vấn ràng buộc theo tên với ODP.NET

SELECT A,B,C FROM FOO WHERE X = :PARAM_X OR :PARAM_X = 0 

Với ODP.NET, tôi phải thêm hai tham số cho các OracleCommand, mà tôi nghĩ là ngu ngốc ...

ODP.NET OracleCommand có thuộc tính để thay đổi hành vi mặc định đó: BindByName. Khi được đặt thành true, các tham số bị ràng buộc bởi tên, đó là những gì tôi muốn. Đáng tiếc là điều này không thực sự giúp tôi, bởi vì:

  • Nó được thiết lập để sai theo mặc định
  • Tôi gần như không bao giờ sử dụng các lớp ADO.NET bê tông một cách rõ ràng, tôi thích sử dụng ADO.NET 2.0 lớp trừu tượng (DbProviderFactory , DbConnection, DbCommand ...) để giảm liên kết với bất kỳ RDBMS cụ thể nào. Vì vậy, tôi không có quyền truy cập vào thuộc tính BindByName, trừ khi tôi truyền rõ ràng đến OracleCommand, mất tất cả lợi ích hoặc sự trừu tượng.
  • Khi sử dụng ASP.NET SqlDataSource, tôi không tự tạo DbCommand, vì vậy tôi không có cơ hội để đặt BindByName thành true (tôi có thể thực hiện trong sự kiện Chọn, nhưng thực sự là một nỗi đau hãy làm điều đó cho mỗi SqlDataSource ...)

Tôi phải xử lý vấn đề đó như thế nào? Có cài đặt BindByNameByDefault ở đâu đó không? (Tôi đã không tìm thấy bất cứ điều gì như thế, nhưng tôi có thể đã bỏ lỡ nó ...)

+0

Tôi chỉ lãng phí 3 giờ vì "tính năng" này! – Grzenio

Trả lời

7

Tôi nghĩ rằng bạn có thể tạo nhà cung cấp của riêng bạn sử dụng các giá trị mặc định bạn muốn sử dụng. Bạn có thể tạo nhà cung cấp đó dễ dàng bằng cách kế thừa tất cả các lớp từ odp.net, chỉ cần điều chỉnh một số thuộc tính như BindByName.

DbProviderfactory sẽ tạo lớp học của bạn thay vì các lớp odp.net bình thường.

+0

Ý tưởng hay, cảm ơn! Tôi nghĩ rằng tôi sẽ thử rằng –

+2

OK, nó có vẻ khả thi, nhưng không phải rất đơn giản ... hầu hết các lớp ODP.NET được niêm phong, vì vậy tôi không thể kế thừa từ họ để ghi đè lên các phương pháp, và theo Reflector có nhiều nơi OracleCommand constructor được gọi một cách rõ ràng ... Dù sao, tôi không thể nghĩ ra bất kỳ giải pháp tốt hơn, vì vậy tôi chấp nhận câu trả lời của bạn. Cảm ơn ! –

1

Đối với việc chấm dứt của nhà cung cấp Microsoft ADO .NET cho Oracle:

  • tôi sẽ đi vào sử dụng nó thay vì ODP NET, vấn đề của bạn là chỉ là một trong những vấn đề rất nhiều với nó. Và khi nó đi, nó vẫn sẽ có sẵn trong .NET 4.0, mặc dù không được hỗ trợ.
  • Nếu Oracle quản lý để hiển thị nhà cung cấp này không sử dụng được, tôi có thể sẽ sử dụng một giải pháp thay thế thương mại như DataDirect ADO.NET Data Provider for Oracle hoặc dotConnect for Oracle, tích hợp đầy đủ vào khung công tác ADO .NET. Và họ đã ủng hộ Khung thực thể, bằng cách này (tôi tin rằng Oracle đã tuyên bố ODP .NET sẽ không).

ODP .NET mất quá nhiều thời gian của tôi rồi.

+0

Bạn có thể đúng về các nhà cung cấp bên thứ ba, nhưng chúng không miễn phí, vì vậy tôi không chắc tôi có thể thuyết phục chủ nhân của tôi mua chúng ... Tuy nhiên hỗ trợ khung Entity là một đối số nghiêm trọng để đưa vào số dư . Tôi không thể hiểu tại sao Oracle không thực hiện nó trong ODP.NET ... –

+0

Tôi khuyên bạn nên dotConnect cho Oracle. Nó là giá trị mỗi đô la bạn phải trả cho nó. – Konamiman

+0

Oracle đã bắt đầu hỗ trợ Entity Framework thực sự, có bản phát hành beta ODP.net với sự hỗ trợ của EF và Linq ngay bây giờ. – Tridus

4

Sử dụng truyền cảm hứng và thừa kế! Nếu bạn đang thực hiện truy cập dữ liệu thông qua một lớp cơ sở dữ liệu trừu tượng, yêu cầu cơ sở dữ liệu thực hiện xử lý ràng buộc tham số.

public abstract class Database 
{ 
    private readonly DbProviderFactory factory; 

    protected Database(DbProviderFactory factory) 
    { 
     this.factory = factory; 
    } 

    public virtual DbCommand CreateCommand(String commandText) 
    { 
     return CreateCommand(CommandType.Text, commandText); 
    } 

    public virtual DbCommand CreateCommand(CommandType commandType, String commandText) 
    { 
     DbCommand command = factory.CreateCommand(); 
     command.CommandType = commandType; 
     command.Text = commandText; 
     return command; 
    } 

    public virtual void BindParametersByName(DbCommand command) 
    { 

    } 
} 

Và chọn tạo một triển khai Oracle cụ thể ghi đè tạo lệnh mặc định hoặc cung cấp tùy chọn ràng buộc tham số theo tên.

public class OracleDatabase : Database 
{ 
    public OracleDatabase() 
     : base(OracleClientFactory.Instance) 
    { 

    } 

    public override DbCommand CreateCommand(CommandType commandType, String commandText) 
    { 
     DbCommand command = base.CreateCommand(commandType, commandText); 
     BindParametersByName(command); 
     return command; 
    } 

    public override void BindParametersByName(DbCommand command) 
    { 
     ((OracleCommand)command).BindByName = true; 
    } 
} 

Mã dựa trên Data Access Application Block trong Enterprise Library.

+0

Điều này rất giống với những gì tôi đã làm cho một dự án. Lớp OracleDatabase cung cấp một điểm mở rộng tốt đẹp quá, để thêm các phương thức tiện lợi mà việc triển khai mặc định ODP.NET không cung cấp. – CodingWithSpike

+0

Mặc dù giải pháp này là hoàn hảo để sử dụng trong mã C#, nó không giúp đỡ trong trường hợp của ASP.NET SqlDataSource: Tôi phải chỉ định một nhà cung cấp ADO.NET, không phải là một lớp truy cập dữ liệu tùy chỉnh ... –

+0

@Thomas Levesque Tôi không quen thuộc với SqlDataSource, nhưng có vẻ như bạn có thể kế thừa từ DataSourceControl và xây dựng lại OracleDataSource của riêng bạn ... âm thanh như thú vị? –

Các vấn đề liên quan