我正在尝试在 ListView 中显示来自 Sqlite 数据库的数据,但获取任务列表不包含 GetEnumerator

问题描述 投票:0回答:1

我可以连接到数据库,并通过断点可以查看任务调用中返回的数据。在我的 Chambers.xaml.cs 文件中,当尝试在 Foreach 例程中使用它来填充 ListView 的绑定变量时,我在该任务的 listchamber 上收到 GetEnumerator 错误。

Chamber.xaml

```
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="MrDiver.Views.Chambers"
             Title="Chambers"
             xmlns:models="clr-namespace:MrDiver.Models"
             BackgroundColor="LightYellow"
             >
       
    <VerticalStackLayout
        Spacing="30"
        HorizontalOptions="Center"
        BackgroundColor="LightGrey"
        >

        <Label Text="DCI EMERGENCY England, Northern Ireland or Wales phone 07831 151523" ></Label>

        <Label Text="DCI EMERGENCY Scotland phone 0345 408 6008 " ></Label>

        <ListView ItemsSource="{Binding ListChambers}">
            <ListView.ItemTemplate>
                <DataTemplate x:DataType="models:Model_Chambers">
                    <StackLayout>
                        <Label Text="{Binding Name}"/>
                        <Label Text="{Binding Town}"/>
                        <Label Text="{Binding Address}"/>
                    </StackLayout>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
        
    </VerticalStackLayout>

</ContentPage>
```

Chamber.xaml.cs

```
using MrDiver.Data;
using MrDiver.Models;
using System.Collections.ObjectModel;

namespace MrDiver.Views;
public partial class Chambers : ContentPage
{
    public ObservableCollection<Model_Chambers> ListChambers { get; set; } = new();
    public Chambers()   
    {
        InitializeComponent();

        PortDatabase portDatabase = new PortDatabase();
        var listChambers = portDatabase.ChamberList();
        ListChambers.Clear();

            foreach (var model_Chambers in listChambers)
            {
                ListChambers.Add(model_Chambers);
            }

    }

}
```

PortDatabase.cs

```

using SQLite;
using MrDiver.Models;

namespace MrDiver.Data
{
    public class PortDatabase
    {
        private readonly SQLiteAsyncConnection _database;

    public static string DBPath { get; } =
            Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Port.db3");

        public PortDatabase()
        {
            // _database is the connection to read the database
            _database = new SQLiteAsyncConnection(DBPath, SQLiteOpenFlags.Create | SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.SharedCache);
            // creates a new table named Coastguard if it doesn't exist
            _database.CreateTableAsync<Model_Chambers>();
            
        }
        public async Task<List<Model_Chambers>> ChamberList() 
        {
           var cham =  await _database.Table<Model_Chambers>().ToListAsync();
             return cham;
        }

    }
} 
```

Model_Chambers.cs

using SQLite;

namespace MrDiver.Models
{
    [Table("ChambersTable")]
    public class Model_Chambers
    {
        [PrimaryKey, AutoIncrement]
        [Column("KEY")]
        public int Key { get; set; }

        [Column("NAME")]
        public string? Name { get; set; }

        [Column("ADDRESS")]
        public string? Address { get; set; }

        [Column("TOWN")]
        public string? Town { get; set; }

        [Column("COUNTY")]
        public string? County { get; set; }

        [Column("NATION")]
        public string? Nation { get; set; }

        [Column("TELEPHONE")]
        public string? Telephone { get; set; }
    }
}

我尝试了在线示例的各种变体,包括而不是简单地使用 Task 列表,但得到了无法转换显式 Typeof 错误。

c# database sqlite visual-studio-code
1个回答
0
投票

listChambers 
Task<List<Model_Chambers>>
。任务是将来具有值的事物的表示,因此您需要等到该值可用才能对其进行迭代。有几种替代方法可以做到这一点:

  1. .ToListAsync()
    更改为
    .ToList()
    ,并调整返回类型以匹配。
  2. 使用
    portDatabase.ChamberList().Result
    。这在功能上应该与选项 1 相同,但使用
    .Result
    是不受欢迎的,因为存在死锁的风险。我认为这些风险不适用于这种特定情况,但需要注意。
  3. 使用使用
    var listChambers = await portDatabase.ChamberList()
    。这需要您的方法被标记为异步。由于构造函数无法标记为异步,因此您需要将代码移至常规方法。您还需要考虑如何处理异常,以及填充列表可能需要一些时间。因此,请使用 try/catch,并考虑在实际数据到达后隐藏“正在加载...”标签。

如果性能不是问题,我会选择选项 1,因为它很简单。如果数据库调用花费明显的时间,选项 3 可能是首选。

© www.soinside.com 2019 - 2024. All rights reserved.