EF + ODP.NET + CLOB = 값은 Null일 수 없습니다 - 매개 변수 이름: byteArray?
우리 프로젝트는 최근에 새로운 Oracle로 업데이트되었습니다.ManagedDataAccess DLLs(v 4.121.2.0) 및 이 오류가 간헐적으로 발생하고 있습니다.우리는 그것을 고치기 위해 무엇을 했는지 제대로 알지 못한 채 몇 번 고쳤습니다.
CLOB 필드가 엔티티 프레임워크의 문자열에 매핑된 다음 제한된 속성 집합이 아닌 전체 엔티티를 끌어오는 LINQ 문에서 선택되어 발생하는 것이라고 확신합니다.
오류:
Value cannot be null.
Parameter name: byteArray
추적 쌓기:
at System.BitConverter.ToString(Byte[] value, Int32 startIndex, Int32 length)
at OracleInternal.TTC.TTCLob.GetLobIdString(Byte[] lobLocator)
at OracleInternal.ServiceObjects.OracleDataReaderImpl.CollectTempLOBsToBeFreed(Int32 rowNumber)
at Oracle.ManagedDataAccess.Client.OracleDataReader.ProcessAnyTempLOBs(Int32 rowNumber)
at Oracle.ManagedDataAccess.Client.OracleDataReader.Read()
at System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.StoreRead()
의심스러운 엔터티 속성:
'Mapped to Oracle CLOB Column'
<Column("LARGEFIELD")>
Public Property LargeField As String
하지만 오라클의 매트릭스별로 필드를 매핑하는 적절한 방법이라고 확신합니다.
생성된 SQL 문에도 명백히 문제가 없습니다.
SELECT
...
"Extent1"."LARGEFIELD" AS "LARGEFIELD",
...
FROM ... "Extent1"
WHERE ...
Ozkan의 제안에 따라 이 Fluent code도 시도해 보았지만, 제 경우에는 영향을 미치지 않는 것 같습니다.
modelBuilder.Entity(Of [CLASS])().Property(
Function(x) x.LargeField
).IsOptional()
업데이트 문제 해결:
광범위한 테스트를 거친 결과, 이것이 구성 문제가 아니라 실제로 버그라는 것을 확신할 수 있었습니다.매우 특정한 상황에서 문제를 일으키는 CLOB의 내용으로 보입니다.오라클 포럼에 교차 게시했는데 더 많은 정보가 필요합니다.
Oracle 12 클라이언트를 설치한 후 동일한 문제가 발생하였습니다.machine.config(C:\Windows\Microsoft)에 있습니다.NET\Framework\v4.0.30319\Config) Oracle로 모든 항목을 제거했습니다.관리되는 데이터 액세스.디렉토리 C:\Windows\Microsoft.NET\어셈블리\GAC_MSILI가 두 Oracle을 모두 제거했습니다.관리 데이터 액세스 및 정책. 4.121.오라클.관리되는 데이터 액세스.그러고 나서 내 C# 프로그램은 오라클을 사용하면서 평소처럼 작동하기 시작했습니다.자체 디렉터리에 있는 ManagedDataAccess dll.
우리는 한 시간 전에 우리 프로젝트에서 이 문제를 만나서 해결책을 찾았습니다.CLOB calumn의 null 값 때문에 이 오류가 발생하고 있습니다.CLOB 열이 있으며 데이터베이스에서 Nullable입니다.EntityFramework 모델에서는 String이지만 Nullable은 아닙니다.컬럼의 Nullable property를 True로 변경하여 EF 모델에서 수정하였습니다.
일부 컴퓨터에서도 이 문제가 발생하여 최신 Oracle을 실행하고 있습니다.ManagedDataAccess.dll(4.121.2.20150926 ODAC 릴리스 4).
우리는 우리의 문제에 대한 해결책을 찾았고, 저는 단지 공유하고 싶었습니다.
이것은 몇몇 컴퓨터에서 발생한 우리의 문제였습니다.
Using connection As New OracleConnection(yourConnectionString)
Dim command As New OracleCommand(yourQuery, connection)
connection.Open()
Using reader As OracleDataReader = command.ExecuteReader()
Dim clobField As String = CStr(reader.Item("CLOB_FIELD"))
End Using
connection.Close()
End Using
여기에 모든 컴퓨터에서 작동하게 만든 솔루션이 있습니다.
Using connection As New OracleConnection(yourConnectionString)
Dim command As New OracleCommand(yourQuery, connection)
connection.Open()
Using reader As OracleDataReader = command.ExecuteReader()
Dim clobField As String = reader.GetOracleClob(0).Value
End Using
connection.Close()
End Using
저는 이것을 해독하기 위해 많은 시간을 들였고 인터넷 여기저기에서 이것저것 조금씩 발견했습니다. 하지만 어디에도 모든 것이 한 곳에 있지 않아서, 제가 배운 것과 해결 방법을 게시하고 싶습니다. 라고윗의 답과 비슷하지만, 저는 그것을 위한 C# 코드를 가지고 있습니다.
오류: 그래서 이 오류가 발생했습니다.while (dr.Read())
선:
Value cannot be null. \r\nParmeter name: byteArray
나는 이것에 대해 인터넷에서 거의 마주치지 못했습니다. 다만 그것이 오류였다는 것을 제외하고는.CLOB
다음에 따르면 null이고 최신 ODAC 릴리스에서 수정된 것으로 추정되는 필드: https://community.oracle.com/thread/3944924
이것에 대한 저의 의견은 사실이 아닙니다!2015년 10월 5일 이후 업데이트가 되지 않고 있습니다(http://www.oracle.com/technetwork/topics/dotnet/utilsoft-086879.html), . 제가 사용하고 있는 12c 패키지는 2016년 4월에 다운로드 되었습니다.
내 것과 거의 비슷한 오류를 가진 다른 사람에 의한 전체 스택 추적: http://pastebin.com/24AfFDnq
Value cannot be null.
Parameter name: byteArray
at System.BitConverter.ToString(Byte[] value, Int32 startIndex, Int32 length)
at OracleInternal.TTC.TTCLob.GetLobIdString(Byte[] lobLocator)
at OracleInternal.ServiceObjects.OracleDataReaderImpl.CollectTempLOBsToBeFreed(Int32 rowNumber)
at Oracle.ManagedDataAccess.Client.OracleDataReader.ProcessAnyTempLOBs(Int32 rowNumber)
at Oracle.ManagedDataAccess.Client.OracleDataReader.Read()
at System.Data.Entity.Core.Common.Internal.Materialization.Shaper`1.StoreRead()
'Mapped to Oracle CLOB Column'
<Column("LARGEFIELD")>
Public Property LargeField As String
'Mapped to Oracle BLOB Column'
<Column("IMAGE")>
Public Property FileContents As Byte()
내가 그것을 접하게 된 계기:약 3,000줄로 된 11열짜리 표를 읽다가였습니다.그 기둥들 중 하나는 사실은NCLOB
(따라서 겉보기엔 이것은 그와 마찬가지로 매우 민감합니다.CLOB
데이터베이스에서 null을 허용하고 일부 값은 비어 있었습니다. 결국 선택사항인 "Notes" 필드였습니다.Notes 필드가 비어 있는 첫번째 행이나 두번째 행에서도 이 오류가 발생하지 않았다는 것이 재미있습니다.768열이 끝날 때까지 오류가 없었고 769열을 시작하려고 했습니다.int
설정한 0에서 시작하여 지금까지 데이터 테이블에 몇 개의 행이 있는지 확인한 후 본 카운터 변수.다음을 사용하면 오류가 발생합니다.
DataSet ds = new DataSet();
OracleDataAdapter adapter = new OracleDataAdapter(cmd);
adapter.Fill(ds);
다음을 사용하는 경우에도 마찬가지입니다.
DataTable dt = new DataTable();
OracleDataReader dr = cmd.ExecuteReader();
dt.Load(dr);
또는 사용한 경우:
OracleDataReader dr = cmd.ExecuteReader();
if (dr.HasRows)
{
while (dr.Read())
{
....
}
}
어디에cmd
. ㅇOracleCommand
, 그래서 아무 차이도 없었습니다.
결의안
다음은 기본적으로 제가 암호를 분석할 때 사용했던 코드입니다.OracleDataReader
a에 할당하기 위해 값을 지정합니다.DataTable
. 사실은 그 정도로 세련되지 않았습니다. 그냥 돌려주기 위해 사용하고 있는 겁니다.dr[i]
.datarow
값이 null일 때와 열한 번째 열일 때(0에서 시작하므로 인덱스 = 10)를 제외하고 모든 경우에 특정 쿼리가 실행되어 내 위치를 알 수 있습니다.NCLOB
열은.
public static DataTable GetDataTableManually(string query)
{
OracleConnection conn = null;
try
{
string connString = ConfigurationManager.ConnectionStrings["MyConn"].ConnectionString;
conn = new OracleConnection(connString);
OracleCommand cmd = new OracleCommand(query, conn);
conn.Open();
OracleDataReader dr = cmd.ExecuteReader(CommandBehavior.CloseConnection);
DataTable dtSchema = dr.GetSchemaTable();
DataTable dt = new DataTable();
List<DataColumn> listCols = new List<DataColumn>();
List<DataColumn> listTypes = new List<DataColumn>();
if (dtSchema != null)
{
foreach (DataRow drow in dtSchema.Rows)
{
string columnName = System.Convert.ToString(drow["ColumnName"]);
DataColumn column = new DataColumn(columnName, (Type)(drow["DataType"]));
listCols.Add(column);
listTypes.Add(drow["DataType"].ToString()); // necessary in order to record nulls
dt.Columns.Add(column);
}
}
// Read rows from DataReader and populate the DataTable
if (dr.HasRows)
{
int rowCount = 0;
while (dr.Read())
{
string fieldType = String.Empty;
DataRow dataRow = dt.NewRow();
for (int i = 0; i < dr.FieldCount; i++)
{
if (!dr.IsDBNull[i])
{
fieldType = dr.GetFieldType(i).ToString(); // example only, this is the same as listTypes[i], and neither help us distinguish NCLOB from NVARCHAR2 - both will say System.String
// This is the magic
if (query == "SELECT * FROM Orders" && i == 10)
dataRow[((DataColumn)listCols[i])] = dr.GetOracleClob(i); // <-- our new check!!!!
// Found if you have null Decimal fields, this is
// also needed, and GetOracleDecimal and GetDecimal
// will not help you - only GetFloat does
else if (listTypes[i] == "System.Decimal")
dataRow[((DataColumn)listCols[i])] = dr.GetFloat(i);
else
dataRow[((DataColumn)listCols[i])] = dr[i];
}
else // value was null; we can't always assign dr[i] if DBNull, such as when it is a number or decimal field
{
byte[] nullArray = new byte[0];
switch (listTypes[i])
{
case "System.String": // includes NVARCHAR2, CLOB, NCLOB, etc.
dataRow[((DataColumn)listCols[i])] = String.Empty;
break;
case "System.Decimal":
case "System.Int16": // Boolean
case "System.Int32": // Number
dataRow[((DataColumn)listCols[i])] = 0;
break;
case "System.DateTime":
dataRow[((DataColumn)listCols[i])] = DBNull.Value;
break;
case "System.Byte[]": // Blob
dataRow[((DataColumn)listCols[i])] = nullArray;
break;
default:
dataRow[((DataColumn)listCols[i])] = String.Empty;
break;
}
}
}
dt.Rows.Add(dataRow);
}
ds.Tables.Add(dt);
}
}
catch (Exception ex)
{
// handle error
}
finally
{
conn.Close();
}
// After everything is closed
if (ds.Tables.Count > 0)
return ds.Tables[0]; // there should only be one table if we got results
else
return null;
}
스키마 테이블 루프에서 발견된 열 유형에 따라 null의 특정 유형을 할당하는 것과 동일하게 조건을 "not null" 측면에 추가할 수 있습니다.if...then
다양한 일을 합니다.GetOracle...
거기 진술서들.이 일을 위해서만 필요하다는 것을 알았습니다.NCLOB
예를 들면 말이죠
크레딧이 제공되어야 하는 곳에 크레딧을 제공하기 위해 원래 코드베이스는 데이터 리더의 데이터 테이블 채우기에서 sarathkumar에 의해 제공된 답변을 기반으로 합니다.
저에게는 간단했습니다!odac v 4.121.1.0에서 이 오류가 발생했습니다.방금 Oracle을 업데이트 했습니다.Managed Data Nuget으로 4.121.2.0에 액세스하여 현재 작동 중입니다.
Oracle을 제거하고 다시 설치하려고 시도한 적이 있습니까?Nugget으로 데이터 액세스 관리?
Oracle을 업그레이드합니다.ManagedDataAccess.dll에서 버전 4.122.1.0으로 해결되었습니다.2017년을 사용하시는 경우 NuGet을 통해 업데이트 할 수 있습니다.
언급URL : https://stackoverflow.com/questions/28593520/ef-odp-net-clob-value-cannot-be-null-parameter-name-bytearray
'programing' 카테고리의 다른 글
SQL Server에서 latin1 varchar의 문자를 MariaDButf8에 삽입하려면 어떻게 인코딩해야 합니까? (0) | 2023.10.24 |
---|---|
Excel에서 OD 데이터 피드의 변경 내용을 게시하는 방법 (0) | 2023.10.24 |
ANTLR을 사용하여 구축된 AST를 출력하는 방법은? (0) | 2023.10.19 |
정방향 클래스 개체에서 속성을 찾을 수 없습니다. (0) | 2023.10.19 |
Spring MVC에 필요한 String 매개 변수가 없습니다. (0) | 2023.10.19 |