diff --git a/Src/Asp.NetCore2/MongoDb.Ado.data/MongoDbCommand.cs b/Src/Asp.NetCore2/MongoDb.Ado.data/MongoDbCommand.cs new file mode 100644 index 000000000..2444fc488 --- /dev/null +++ b/Src/Asp.NetCore2/MongoDb.Ado.data/MongoDbCommand.cs @@ -0,0 +1,100 @@ +using System; +using System.Data.Common; +using System.Threading.Tasks; +using MongoDB.Driver; +using MongoDB.Bson; +using System.Data; +namespace MongoDb.Ado.data +{ + + public class MongoDbCommand : DbCommand + { + private string _commandText; + private MongoDbConnection _connection; + private int _commandTimeout; + + public MongoDbCommand() + { + } + + public MongoDbCommand(string commandText, MongoDbConnection connection) + { + _commandText = commandText; + _connection = connection; + } + + public override string CommandText + { + get => _commandText; + set => _commandText = value; + } + + public override int CommandTimeout + { + get => _commandTimeout; + set => _commandTimeout = value; + } + + public override CommandType CommandType { get; set; } = CommandType.Text; + + protected override DbConnection DbConnection + { + get => _connection; + set => _connection = (MongoDbConnection)value; + } + + protected override DbParameterCollection DbParameterCollection => throw new NotSupportedException("MongoDbCommand does not support parameters yet."); + + protected override DbTransaction DbTransaction { get; set; } + + public override bool DesignTimeVisible { get; set; } + + public override UpdateRowSource UpdatedRowSource { get; set; } + + public override void Cancel() + { + // MongoDB driver does not support canceling a command. + } + + public override int ExecuteNonQuery() + { + throw new NotSupportedException("MongoDbCommand does not support ExecuteNonQuery directly."); + } + + public override object ExecuteScalar() + { + var collection = GetCollection(); + var document = collection.Find(FilterDefinition.Empty).FirstOrDefault(); + return document; + } + + protected override DbDataReader ExecuteDbDataReader(CommandBehavior behavior) + { + var collection = GetCollection(); + var cursor = collection.Find(FilterDefinition.Empty).ToCursor(); + return new MongoDbDataReader(cursor); + } + + public override void Prepare() + { + // No preparation needed for MongoDB commands + } + + private IMongoCollection GetCollection() + { + if (_connection == null || _connection.State != ConnectionState.Open) + throw new InvalidOperationException("Connection must be open."); + + if (string.IsNullOrWhiteSpace(_commandText)) + throw new InvalidOperationException("CommandText must be set to the collection name."); + + return _connection.GetDatabase().GetCollection(_commandText); + } + + protected override DbParameter CreateDbParameter() + { + throw new NotImplementedException(); + } + } + +} diff --git a/Src/Asp.NetCore2/MongoDb.Ado.data/MongoDbConnection.cs b/Src/Asp.NetCore2/MongoDb.Ado.data/MongoDbConnection.cs index 52bea559f..e744c2c76 100644 --- a/Src/Asp.NetCore2/MongoDb.Ado.data/MongoDbConnection.cs +++ b/Src/Asp.NetCore2/MongoDb.Ado.data/MongoDbConnection.cs @@ -13,17 +13,17 @@ namespace MongoDb.Ado.data private static readonly Dictionary _clientCache = new Dictionary(StringComparer.OrdinalIgnoreCase); private static readonly object _lock = new object(); - private string _originalConnectionString; + private string _originalConnectionString; private IMongoDatabase _database; private string _databaseName; private ConnectionState _state = ConnectionState.Closed; - + public override string Database => _databaseName; public override string DataSource => _client?.Settings?.Server?.ToString() ?? ""; public override string ServerVersion => "MongoDB_" + (_client?.Cluster?.Description?.ClusterId.ToString() ?? "Unknown"); public override ConnectionState State => _state; - public override string ConnectionString { get => _originalConnectionString; set => _originalConnectionString=value; } + public override string ConnectionString { get => _originalConnectionString; set => _originalConnectionString = value; } private MongoClient _client; diff --git a/Src/Asp.NetCore2/MongoDb.Ado.data/MongoDbDataReader.cs b/Src/Asp.NetCore2/MongoDb.Ado.data/MongoDbDataReader.cs new file mode 100644 index 000000000..ea80c408b --- /dev/null +++ b/Src/Asp.NetCore2/MongoDb.Ado.data/MongoDbDataReader.cs @@ -0,0 +1,122 @@ +using System; +using System.Collections.Generic; +using System.Data.Common; +using MongoDB.Driver; +using MongoDB.Bson; +using System.Data; +using System.Collections; + +namespace MongoDb.Ado.data +{ + + public class MongoDbDataReader : DbDataReader + { + private readonly IAsyncCursor _cursor; + private IEnumerator _enumerator; + private BsonDocument _current; + + public MongoDbDataReader(IAsyncCursor cursor) + { + _cursor = cursor; + _enumerator = cursor.ToEnumerable().GetEnumerator(); + } + + public override bool Read() + { + if (_enumerator.MoveNext()) + { + _current = _enumerator.Current; + return true; + } + return false; + } + + public override int FieldCount => _current?.ElementCount ?? 0; + + public override object GetValue(int ordinal) + { + if (_current == null) + throw new InvalidOperationException("No current document."); + + var element = GetElementByOrdinal(ordinal); + return BsonTypeMapper.MapToDotNetValue(element.Value); + } + + public override string GetName(int ordinal) + { + var element = GetElementByOrdinal(ordinal); + return element.Name; + } + + public override int GetOrdinal(string name) + { + int i = 0; + foreach (var elem in _current.Elements) + { + if (elem.Name.Equals(name, StringComparison.OrdinalIgnoreCase)) + return i; + i++; + } + throw new IndexOutOfRangeException($"Field '{name}' not found."); + } + + private BsonElement GetElementByOrdinal(int ordinal) + { + if (_current == null) + throw new InvalidOperationException("No current document."); + + int i = 0; + foreach (var elem in _current.Elements) + { + if (i == ordinal) + return elem; + i++; + } + throw new IndexOutOfRangeException(); + } + + public override bool HasRows => true; + public override bool IsClosed => false; + public override int RecordsAffected => -1; + public override bool NextResult() => false; + + public override object this[int ordinal] => GetValue(ordinal); + public override object this[string name] => GetValue(GetOrdinal(name)); + + // 下面这些可以根据需要进一步实现或抛异常 + public override bool GetBoolean(int ordinal) => (bool)GetValue(ordinal); + public override byte GetByte(int ordinal) => (byte)GetValue(ordinal); + public override long GetBytes(int ordinal, long dataOffset, byte[] buffer, int bufferOffset, int length) => throw new NotSupportedException(); + public override char GetChar(int ordinal) => (char)GetValue(ordinal); + public override long GetChars(int ordinal, long dataOffset, char[] buffer, int bufferOffset, int length) => throw new NotSupportedException(); + public override string GetDataTypeName(int ordinal) => GetFieldType(ordinal).Name; + public override DateTime GetDateTime(int ordinal) => (DateTime)GetValue(ordinal); + public override decimal GetDecimal(int ordinal) => (decimal)GetValue(ordinal); + public override double GetDouble(int ordinal) => (double)GetValue(ordinal); + public override Type GetFieldType(int ordinal) => GetValue(ordinal)?.GetType() ?? typeof(object); + public override float GetFloat(int ordinal) => (float)GetValue(ordinal); + public override Guid GetGuid(int ordinal) => (Guid)GetValue(ordinal); + public override short GetInt16(int ordinal) => (short)GetValue(ordinal); + public override int GetInt32(int ordinal) => (int)GetValue(ordinal); + public override long GetInt64(int ordinal) => (long)GetValue(ordinal); + public override string GetString(int ordinal) => (string)GetValue(ordinal); + + public override IEnumerator GetEnumerator() + { + throw new NotImplementedException(); + } + + public override int GetValues(object[] values) + { + throw new NotImplementedException(); + } + + public override bool IsDBNull(int ordinal) + { + throw new NotImplementedException(); + } + + public override int Depth => 0; + } + +}