потеря данных при передаче объекта SqlDataReader методу, которому требуется интерфейс IDataReader

У меня есть метод, которому в качестве параметра требуется объект SqlDataReader, и у меня есть тесты, в которых я издевался над этим объектом, и все работало нормально.

Но теперь мне нужно изменить этот метод. Теперь он должен вызывать только новый метод, который имеет IDataReader в качестве параметра, и это проблема, потому что, когда я передаю смоделированный SqlDataReader в качестве параметра нового метода, он теряет свои данные, и я не знаю почему.

Что-то вроде этого:

void method(SqlDataReader mockedObject)
{
   // example property
   mockedObject.FieldCount; // for example the value is 1;
   newMethod(mockedObject);
}

void newMethod(IDataReader newObject)
{
   // example property
   newObject.FieldCount // here value is 0;
}

Я заметил, что если я копирую только объект SqlDataReader в новую переменную типа IDataReader, данные также очищаются.

Что-то вроде этого:

void method(SqlDataReader mockedObject)
{
   IDataReader variable = mockedObject;
}

правильный код:

=========================================================================================
        [TestMethod()]
    [DeploymentItem("IICMS.dll")]
    public void CheckNullableDateTimeTest_SqlDataReader_Valid()
    {
        MockRepository mocks = new MockRepository();
        SqlDataReader reader = mocks.DynamicMock<SqlDataReader>();
        string column = "test";
        DateTime? expected = new DateTime(2, 1, 1);
        Nullable<DateTime> actual;

        reader.Stub(r => r[column]).Return(expected);
        reader.Stub(r => r.FieldCount).Return(1);
        mocks.ReplayAll();

        actual = Utility_Accessor.CheckNullableDateTime(reader, column);
        Assert.AreEqual(expected, actual);
    }
======================================================================================
        public static DateTime? CheckNullableDateTime(SqlDataReader read, string column)
    {
        return GetValue<DateTime?>(read, column, null);
    }
======================================================================================
public static T GetValue<T>(IDataReader reader, string columnName, T defaultValue)
    {
        try
        {
            for (int i = 0; i < reader.FieldCount; i++)
            {
                if (reader.GetName(i) == columnName)
                {
                    object value = reader[i];
                    return Convert.IsDBNull(value) ? defaultValue : (T)value;
                }
            }

            return defaultValue;
        }
        catch
        {
            return defaultValue;
        }
    }

Итак, код есть, второй и третий методы находятся в другой dll, но это ни на что не влияет. Объект издевается в RhinoMocks;)

Данные теряются после передачи объекта SqlDataReader (чтения) в метод GetValue (т.е. FieldCount равно 0, в методе Check .. оно имеет правильное значение = 1)


person morel    schedule 09.10.2012    source источник
comment
Итак .. означает ли это, что если вы вызовете FieldCount дважды (даже в том же методе), вы получите два разных результата: 1 и затем 0?   -  person Patrick    schedule 09.10.2012
comment
Если нет, не заменяется ли FieldCount ключевым словом new?   -  person Patrick    schedule 09.10.2012
comment
Обратите внимание, что вы на самом деле не копируете объект, вы просто конвертируете ссылку, ничего не происходит, поскольку SqlDataReader не имеет никаких явных или неявных операторов преобразования.   -  person casperOne    schedule 09.10.2012
comment
@casperOne в порядке, но IDataReader - это интерфейс, а SqlDataReader реализует его, поэтому я должен иметь возможность передать его второму методу, не теряя свои данные (т.е. параметр FieldCount) [/ br] Патрик: если вы вызовете его дважды, значение будет такое же, но если попробовать поставить? читатель в новый объект IDataReader, а затем вызовите это свойство, оно будет другим   -  person morel    schedule 09.10.2012
comment
Я не возражаю с этим, но просто проясняю, что нет копирования на новый объект или чего-то в этом роде.   -  person casperOne    schedule 09.10.2012
comment
SqlDataReader - это один из System.Data или ваш собственный издевательский класс? Сохранится ли проблема, если вы введете ((IDataReader)mockedObject).FieldCount?   -  person Patrick    schedule 09.10.2012
comment
хорошо, я понял, спасибо за ответ, но я все еще в ... :) @Patrick Я проверю;) Итак, я проверил, и после этого значение изменилось (потеряно)   -  person morel    schedule 09.10.2012
comment
@ user1732439: А вы используете SqlDataReader из пространства имен System.Data?   -  person Patrick    schedule 09.10.2012
comment
@morel: Я не об этом спрашивал ..   -  person Patrick    schedule 09.10.2012
comment
@Patrick: это пространство имен System.Data.SqlClient, так что это то, о чем вы просили;)   -  person morel    schedule 09.10.2012
comment
Я дуфус .. Хм, ну. Затем вам нужно показать нам код, который вы используете для создания, и передать читателю в method, основываясь на том, что у вас есть в вашем вопросе прямо сейчас, я не вижу в этом ничего плохого.   -  person Patrick    schedule 09.10.2012
comment
@Patrick Я отредактировал сообщение, так что вы можете проверить весь код   -  person morel    schedule 09.10.2012


Ответы (1)


Я не могу это объяснить, но изменение метода тестирования на форму ниже делает доступными все поля объекта в каждом методе (CheckNullString и GetValue):

    [TestMethod()]
    [DeploymentItem("IICMS.dll")]
    public void CheckNullableDateTimeTest_SqlDataReader_Valid()
    {
        MockRepository mocks = new MockRepository();
        SqlDataReader reader = mocks.DynamicMock<SqlDataReader>();
        IDataReader reader2 = reader;
        string column = "test";
        DateTime? expected = new DateTime(2,1,1);
        DateTime? actual;

        reader.Stub(r => r[column]).Return(invalidValue);
        reader.Stub(r => r[0]).Return(invalidValue);
        reader.Stub(r => r.FieldCount).Return(1);
        reader.Stub(r => r.GetName(0)).Return(column);

        reader2.Stub(r => r[column]).Return(invalidValue);
        reader2.Stub(r => r[0]).Return(invalidValue);
        reader2.Stub(r => r.FieldCount).Return(1);
        reader2.Stub(r => r.GetName(0)).Return(column);
        mocks.ReplayAll();

        actual = Utility_Accessor.CheckNullString(reader, column);
        Assert.AreEqual(expected, actual);
    }
person morel    schedule 11.10.2012