Oracle ODP.Net与实体框架6 - 从表视图中选择ORA-00955

BLu*_*LuM 6 c# oracle entity-framework

我已经创建了应用程序,首先使用ODP.Net并且没有实体 - 效果很好.

static void Main(string[] args)
{
    OracleConnection con = new OracleConnection();

    //using connection string attributes to connect to Oracle Database
    con.ConnectionString = "user id=****;password=****;data source=" +
        "(DESCRIPTION=(ADDRESS=(PROTOCOL=TCP)(HOST=server.org.net)(PORT=1521))(CONNECT_DATA=(SERVER=dedicated)(SERVICE_NAME=ora1)))";
    con.Open();
    Console.WriteLine("Connected to Oracle" + con.ServerVersion);

    OracleCommand command = con.CreateCommand();
    command.CommandText = "SELECT ITEM FROM TEST.ORDERS";

    OracleDataReader reader = command.ExecuteReader();

    while (reader.Read())
    {
        Console.WriteLine("\t{0}",
            reader[0]);
    }
    reader.Close();

    // Close and Dispose OracleConnection object
    con.Close();
    con.Dispose();
    Console.WriteLine("Disconnected");
    Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)

TEST.ORDERS是一个视图.

第二个程序正在使用ODP.Net和EntityFramework,并且manaly创建了DbSet类(它在Npgsql.EntityFramework上进行了测试,效果很好,完美地复制了Oracle的视图).应用程序返回错误:ORA-00955.我注意到当"Schema"的名称更改为没有"ORDER"视图的名称时,程序会创建具有相同名称的表.这是我对DbSet的开始:

[Table("ORDERS", Schema = "TEST")]
Run Code Online (Sandbox Code Playgroud)

它可能是错的.但我不知道如何构建可以访问此视图的实体.用户只有SELECT权限.我想做只读操作.

Hus*_*vik 6

实体框架提供程序的 Oracle 实现非常差,但有一些方法可以使其工作。

  1. 简单但烦人 - 使用 NULL 或自己的数据库初始值设定项实现:

    Database.SetInitializer<DatabaseContext>(null);
    
    Run Code Online (Sandbox Code Playgroud)

或者

class DatabaseInitializer : IDatabaseInitializer<DatabaseContext>
{
    public void InitializeDatabase(DatabaseContext context)
    {
        // your implementation
    }
}

Database.SetInitializer(new DatabaseInitializer());
Run Code Online (Sandbox Code Playgroud)

在第一次访问您的数据库之前设置初始化。

  1. 如果您想使用迁移,请创建您的视图,然后在忽略更改的情况下添加迁移,例如使用包 console add-migration initial -ignorechanges。这将使 EF 忽略 DB 模式和模型之间的不一致(因为它只检查来自 的表ALL_TABLES,而不是视图),因此它不会尝试创建表。Oracle EF 实现中有一个错误,如果初始迁移为空,它会删除并重新创建__MigrationHistory表,因此您的初始迁移必须在添加视图迁移之前至少包含一个表,或者您需要在之后添加一个表。


Sae*_*jad 3

你可以在你里面使用Keyless Entity Types和使用ToViewFluent api DbContext。当您将实体定义为ToView并进行迁移时,EF假设该视图已存在于您的数据库中并且不会尝试创建它。

所以首先创建模型:

  public class KeyLessModel
    {
        public string Item { get; set; }
    }
Run Code Online (Sandbox Code Playgroud)

并在DbContext

protected override void OnModelCreating(ModelBuilder modelBuilder)
        {
            modelBuilder.Entity<KeyLessModel>().ToView("ORDERS", "TEST");

        }

        public DbSet<KeyLessModel> KeyLessModels { get; set; }
Run Code Online (Sandbox Code Playgroud)

要从视图中获取数据,只需这样调用:

var items = _dbContext.KeyLessModels.ToList();
Run Code Online (Sandbox Code Playgroud)

我已经测试过EF Core 3.1并且工作正常。