Skip to content

Files

Latest commit

4650f41 · Jan 11, 2022

History

History
172 lines (130 loc) · 5.9 KB

File metadata and controls

172 lines (130 loc) · 5.9 KB

八、在 C# 中插入数据

在本练习中,我们将向名为moviesDb的数据库中插入一些数据。由于我们将研究两种插入数据的方式,我们将把数据存储到两个集合中(基于 T2 的对象的movies_bson和基于概念验证模型的数据的movies_poco)。从技术上来说,一旦保存数据,应该没有区别。

为了做到这一点,我们需要一些样本数据,如GetBsonMovies()方法中所定义的,该方法返回一个BsonDocuments数组。

代码清单 78:返回一个电影的文档数组

  public static BsonDocument[] GetBsonMovies()
  {
      BsonDocument sevenSamurai = new BsonDocument()
      {
          { "name" , "The Seven Samurai" },
          { "directorName" , " Akira Kurosawa" },
          { "actors", new BsonArray {
              new BsonDocument("name", "Toshiro Mifune"),
              new BsonDocument("name", "Takashi Shimura")}},
          { "year" , 1954 }
      };

      BsonDocument theGodfather = new BsonDocument()
      {
          { "name" , "The Godfather" },
          { "directorName" , "Francis Ford Coppola" },
          { "actors", new BsonArray {
              new BsonDocument("name", "Marlon Brando"),
              new BsonDocument("name", "Al Pacino"),
              new BsonDocument("name", "James Caan")} },
          { "year" , 1972 }
      };

      return new BsonDocument[] { sevenSamurai,  theGodfather };
  }

我们可以使用集合级别的InsertManyInsertManyAsync方法插入数据。GetDatabaseReference方法已经在前面提到过了,这只是一个自动引用数据库的辅助方法。

在插入一个文档的情况下,我们将使用InsertOneInsertOneAsync方法,与上述方法相反。

代码清单 79:将电影插入数据库

public static async Task Insert<T>(T[] movies, string dbName, string tableName)
{
    var db = DatabaseHelper.GetDatabaseReference("localhost", dbName);

    var moviesCollection = db.GetCollection<T>(tableName);
    await moviesCollection.InsertManyAsync(movies);
}

insert方法是接受不同种类的movie数组的通用方法,因为我们将使用相同的方法发送基于 POCO 对象的电影列表。

| | 提示:在 MongoDB C# 驱动程序中使用任何方法的一般规则是使用异步方法(如果可用),而不是同步方法。这本书可能并不总是遵循这个规则。 |

我们将Insert方法称为:

代码清单 80:调用插入方法

BsonDocument[] movies = MovieManager.GetBsonMovies();
MovieManager.Insert<BsonDocument>(movies, "moviesDb", "movies_bson").Wait();

不要被MovieManager类所迷惑,它是作为一个辅助类创建的,包含方法GetBsonMoviesInsert<T>(..)

运行此代码后,查询movies_bson集合时,结果如下。

图 42 存储在数据库中的 Bson 格式的电影

正如我们之前看到的那样,BsonDocument的替代方法是使用POCO类来表示对象,在这种情况下,我们将首先声明一个Movie对象的数组。

代码清单 81 获取电影列表作为数组

public static Movie[] GetMovieList()
{
    Movie sevenSamurai = new Movie()
    {
        Name = "Seven Samurai",
        Director = "Akira Kurosawa",
        Year = 1954,
        Actors = new Actor[]
        {
            new Actor {Name = "Toshiro Mifune"},
            new Actor {Name = "Takashi Shimura"},
        }
    };

    Movie theGodFather = new Movie()
    {
        Name = "The Godfather",
        Director = "Francis Ford Coppola",
        Year = 1972,
        Actors = new Actor[]
        {
            new Actor {Name = "Marlon Brando"},
            new Actor {Name = "Al Pacino"},
        },
        Metadata = new BsonDocument("href", "http://thegodfather.com")
    };
    return new Movie[] { sevenSamurai, theGodFather };
} 

但是,在调用Insert<Movie>()方法之前,正如我们之前看到的,我们需要调用RegisterClassMap,这将使驱动程序知道 POCO 对象和所需序列化之间的映射。映射器的完整代码和insert方法的调用如下。

代码清单 82:完整的对象到 BSON 映射

public class BsonMapper
{
    public static void Map()
    {
        if (!BsonClassMap.IsClassMapRegistered(typeof(Movie)))
        {
            BsonClassMap.RegisterClassMap<Movie>(movie =>
            {
                movie.MapIdProperty(p => p.MovieId)
                          .SetIdGenerator(new StringObjectIdGenerator());
                movie.MapProperty(p => p.Name).SetElementName("name");
                movie.MapProperty(p => p.Director).SetElementName("directorName");
                movie.MapProperty(p => p.Year).SetElementName("year");
                movie.MapProperty(p => p.Actors).SetElementName("actors");
                movie.UnmapProperty(p => p.Age);
                movie.MapExtraElementsMember(p => p.Metadata);
                movie.SetIgnoreExtraElements(true);
            });
        }

 if (!BsonClassMap.IsClassMapRegistered(typeof(Actor)))
 {
     BsonClassMap.RegisterClassMap<Actor>(actor =>
     {
         actor.MapProperty(p => p.Name).SetElementName("name");
     });
 }
    }
}

从调用者的角度来看,代码是什么样的?

代码清单 83:使用概念验证类映射插入电影

private static void Main(string[] args)
{
    Movie[] movies = MovieManager.GetMovieList();
    BsonMapper.Map(); //map the class to the MongoDB representation.
    MovieManager.Insert<Movie>(movies, "moviesDb", "movies_poco").Wait();
}

为了有所作为,我们将数据存储到movies_poco集合中。这纯粹是为了展示功能。这两种方法是相同的,在生产系统中,我们将使用相同的集合。

我们也来关注一下bson mape。Map() 调用。这应该只在应用启动时执行一次。

插入两部电影的结果如下。结论是两种方法得到的结果完全相同。

图 43:插入数据库的电影。