.NET MAUI SQLite CreateTableAsync 在没有异常的情况下崩溃应用程序

huangapple go评论76阅读模式
英文:

.NET MAUI SQLite CreateTableAsync crashes app without exception

问题

我目前正在尝试在我的MAUI项目中使用SQLite。
我之前在WPF中使用过它,没有任何问题,而且我在MAUI中也是以完全相同的方式使用,但却没有成功。

所有在线解决方案对我都不起作用,也许有人可以帮我解决。

以下是我的代码:

我正在调用createProfiles(),它调用ProfileService.AddProfile(Profile),然后调用Init()
Init()中,我的应用程序运行到await db.CreateTableAsync<Profile>();,然后关闭,没有抛出任何异常。

ProfileService.cs

public class ProfileService : IProfileService
{
    SQLiteAsyncConnection db;

    async Task Init()
    {
        if (db != null)
            return;

        var databasePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Profiles.db");

        db = new SQLiteAsyncConnection(databasePath);

        await db.CreateTableAsync<Profile>();
    }

    public async Task AddProfile(Profile profile)
    {
        await Init();
        var id = await db.InsertAsync(profile);
    }
}

ViewModel

private async void createProfiles()
{
    Profile tempProfile = new Profile
    {
        Name = "Test",
        Hostname = "0.0.0.0",
        Port = 23,
    };

    await ProfileService.AddProfile(tempProfile);
}

Profile.cs

public class Profile
{
    [PrimaryKey, AutoIncrement]
    public int Id { get; set; }
    public string Name { get; set; }
    public string Hostname { get; set; }
    public int Port { get; set; }

    public Profile()
    {

    }
}

我尝试在Profile构造函数中设置默认值,但没有成功。
我还尝试将await ProfileService.AddProfile(tempProfile);包装在一个单独的线程中,但也没有成功。

英文:

im currently trying to use SQLite in my MAUI Project.
I have used it before in WPF without any issues and I did it the exact same way in MAUI without success.

All of the solutions online didnt work for me, maybe someone can help me out.

Here is my code:

Im calling createProfiles() which calls ProfileService.AddProfile(Profile) which then calls Init().
In Init() my App runs till await db.CreateTableAsync<Profile>(); and then closes without any exception being thrown.

ProfileService.cs

public class ProfileService : IProfileService
{
    SQLiteAsyncConnection db;

        async Task Init()
        {
            if (db != null)
                return;

            var databasePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Profiles.db");

            db = new SQLiteAsyncConnection(databasePath);

            await db.CreateTableAsync<Profile>();
        }

        public async Task AddProfile(Profile profile)
        {
            await Init();
            var id = await db.InsertAsync(profile);
        }
}

ViewModel

private async void createProfiles()
        {
            Profile tempProfile = new Profile
            {
                Name = "Test",
                Hostname = "0.0.0.0",
                Port = 23,
            };

            await ProfileService.AddProfile(tempProfile);
        }

Profile.cs

public class Profile
    {
        [PrimaryKey, AutoIncrement]
        public int Id { get; set; }
        public string Name { get; set; }
        public string Hostname { get; set; }
        public int Port { get; set; }

        public Profile()
        {

        }
    }

I have tried setting default values in the Profile constructor, without success.
I also tried wrapping await ProfileService.AddProfile(tempProfile); in a seperat thread, without success.

答案1

得分: 1

你是否按照Microsoft的文档中的指南进行操作了?
你需要一个额外的库SQLitePCLRaw.bundle_green,以使sqlite-pcl-net能够在各个平台上运行。
1: https://www.nuget.org/packages/SQLitePCLRaw.bundle_green/
2: https://learn.microsoft.com/en-us/dotnet/maui/data-cloud/database-sqlite?view=net-maui-7.0#:~:text=.NET%20MAUI%20local%20databases%201%20Install%20the%20SQLite,4%20Access%20data%20...%205%20Advanced%20configuration%20

英文:

Have you followed the guide in the microsoft docs?
You need an additional library
SQLitePCLRaw.bundle_green to make sqlite-pcl-net work on each platform.

答案2

得分: 1

也许在创建连接时尝试使用这些标志。您的输出表明文件不存在,所以也许使用“Create”标志可以解决您的问题,或者确保在使用其他数据库操作之前自己创建文件。

public const SQLiteOpenFlags Flags =
    // 以读/写模式打开数据库
    SQLiteOpenFlags.ReadWrite |
    // 如果不存在,则创建数据库
    SQLiteOpenFlags.Create |
    // 启用多线程数据库访问
    SQLiteOpenFlags.SharedCache;

Database = new SQLiteAsyncConnection(path, Flags);
英文:

Maybe try using these flags when creating the connection. Your output indicates your file does not exist, so maybe the flag Create might solve your issue or make sure you create the file on your own before you use other database operations.

public const SQLiteOpenFlags Flags =
        // open the database in read/write mode
        SQLiteOpenFlags.ReadWrite |
        // create the database if it doesn't exist
        SQLiteOpenFlags.Create |
        // enable multi-threaded database access
        SQLiteOpenFlags.SharedCache;

Database = new SQLiteAsyncConnection(path, Flags);

答案3

得分: 0

public interface IProfileRepo
{
    Task<bool> AddProfileAsync(Profile profile);
}

public class ProfileRepo : IProfileRepo
{
    private readonly SQLiteAsyncConnection _connect;

    public ProfileRepo(SQLiteAsyncConnection connect)
    {
        _connect = connect;
        Task.Run(() => this.CreateTable()).Wait();
    }

    private async Task CreateTable()
    {
        await _connect.CreateTableAsync<Profile>();
    }
    //Other methods Add, Delete and etc.
}

public class UnitOfWork
{
    private readonly SQLiteAsyncConnection _connect;
    private IProfileRepo _profileRepo;

    public UnitOfWork(string dbPath)
    {
        _connect = new SQLiteAsyncConnection(dbPath);
    }

    public IProfileRepo ProfileRepo
    {
        get
        {
            return _profileRepo = _profileRepo ?? new ProfileRepo(_connect);
        }
    }
}

public class ProfileService
{
    public async Task Add(Profile profile)
    {
        await App.UnitOfWork.ProfileRepo.AddProfileAsync(profile);
    }
}

public partial class App : Application
{
    public static UnitOfWork UnitOfWork
    {
        get
        {
            if (unitOfWork == null)
            {
                unitOfWork = new UnitOfWork(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "TestDB.db3");
            }
            return unitOfWork;
        }
    }
}

private void DeleteLocalDB()
{
    var file = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "TestDB.db3");
    if (File.Exists(file))
    {
        File.Delete(file);
    }
}

Used nuget package:

<PackageReference Include="sqlite-net-pcl" Version="1.8.116" />
英文:
  public interface IProfileRepo
        {
            Task&lt;bool&gt; AddProfileAsync(Profile profile);    
        }    

  public class ProfileRepo : IProfileRepo
    {
      private readonly SQLiteAsyncConnection _connect;
            public ProfileRepo (SQLiteAsyncConnection connect)
            {
                _connect = connect;
                Task.Run(() =&gt; this.CreateTable()).Wait();
            }
    
            private async Task CreateTable()
            {
                await _connect.CreateTableAsync&lt;Profile&gt;();
            }
            //Other methods Add, Delete and etc.
    }

    public class UnitOfWork
        {
            private readonly SQLiteAsyncConnection _connect;
            private IProfileRepo _profileRepo;
            public UnitOfWork(string dbPath)
            {
                _connect = new SQLiteAsyncConnection(dbPath);
            }
            public IProfileRepo ProfileRepo
            {
                get
                {
                    return _profileRepo = _profileRepo ?? new ProfileRepo(_connect);
                }
            }      
        }

public class ProfileService
{
        public async Task Add(Profile profile)
        {
          await App.UnitOfWork.ProfileRepo.Add(profile);
        }
}


public partial class App : Application
{
public static UnitOfWork UnitOfWork
        {
            get
            {
                if (unitOfWork == null)
                {
                    unitOfWork = new UnitOfWork(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), &quot;TestDB.db3&quot;));
                }
                return unitOfWork;
            }
        }
}

During development, you may want to drop the database every time the application starts.

private void DeleteLocalDB()
        {           
            var file = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), &quot;TestDB.db3&quot;);
            if(File.Exists(file))
            {
                File.Delete(file);
            }            
        }

Used nuget package

 &lt;PackageReference Include=&quot;sqlite-net-pcl&quot; Version=&quot;1.8.116&quot; /&gt;

答案4

得分: 0

I found a solution myself.
I will try to explain it for everyone who has the same issue in the future.

After looking at the Debug Log from my physical Android device I found the following entries:
Debug entries

This clearly says that some SQLite assemblies failed to load.

The only thing I had to do now was:

  • Uninstall the app on the phone
  • Add <EmbedAssembliesIntoApk>true</EmbedAssembliesIntoApk> to my .csproj, to turn off Fast Deploy.

And now it all works fine .NET MAUI SQLite CreateTableAsync 在没有异常的情况下崩溃应用程序

英文:

I found a solution myself.
I will try to explain it for everyone who has the same issue in the future.

After looking at the Debug Log from my physical Android device I found the following etries:
Debug entries

This clearly says, that some SQLite assemblies failed to loaded.

The only thing I had to do now was:

  • Unistall the app on the phone
  • Add &lt;EmbedAssembliesIntoApk&gt;true&lt;/EmbedAssembliesIntoApk&gt; to my .csproj, to turn off Fast Deploy.

And now it all works fine .NET MAUI SQLite CreateTableAsync 在没有异常的情况下崩溃应用程序

huangapple
  • 本文由 发表于 2023年3月7日 23:00:43
  • 转载请务必保留本文链接:https://go.coder-hub.com/75663645.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定